+ # 示例:使用仓库内置的最小样例(仅 1 个 JSON)
+ INGEST_SOURCE_DIR=../tmp/single_ingest
+ ```
+3) 安装依赖:
```bash
cd etl_billiards
pip install -r requirements.txt
- # 开发模式:pip install -e .
```
-3. **配置 `.env`**
+4) 回放入库(ODS)→ 装载 DWD → 质检(可用 `--ingest-source` 覆盖 `INGEST_SOURCE_DIR`):
```bash
- cp .env.example .env
- # 核心项
- PG_DSN=postgresql://user:pwd@host:5432/LLZQ
- API_BASE=https://api.example.com
- API_TOKEN=your_token
- STORE_ID=2790685415443269
- EXPORT_ROOT=/path/to/export
- LOG_ROOT=/path/to/logs
+ python -m cli.main --pipeline-flow INGEST_ONLY --tasks INIT_ODS_SCHEMA,INIT_DWD_SCHEMA
+ python -m cli.main --pipeline-flow INGEST_ONLY --tasks MANUAL_INGEST --ingest-source "../tmp/single_ingest"
+ python -m cli.main --pipeline-flow INGEST_ONLY --tasks DWD_LOAD_FROM_ODS
+ python -m cli.main --pipeline-flow INGEST_ONLY --tasks DWD_QUALITY_CHECK
+ # 报表:reports/dwd_quality_report.json
```
- 配置的生效顺序为 “默认值” < “环境变量/.env” < “CLI 参数”。
-4. **运行任务**
+
+> 可按需单独运行:
+> - 仅建表:`python -m cli.main --tasks INIT_ODS_SCHEMA`
+> - 仅 ODS 灌入:`python -m cli.main --tasks MANUAL_INGEST`
+> - 仅 DWD 装载:`python -m cli.main --tasks INIT_DWD_SCHEMA,DWD_LOAD_FROM_ODS`
+
+> Windows:可用 `etl_billiards/run_ods.bat` 一键执行 ODS 建表 + 灌入示例 JSON(`INIT_ODS_SCHEMA` + `MANUAL_INGEST`)。
+
+## 正式环境(在线抓取 → 更新 ODS → 更新 DWD)
+
+**核心入口 CLI(推荐在 `etl_billiards/` 目录执行)**
+- `python -m cli.main`
+
+### 必备配置(建议通过环境变量或 `.env`)
+- 数据库:`PG_DSN`、`STORE_ID`
+- 在线抓取:`API_TOKEN`(可选 `API_BASE`、`API_TIMEOUT`、`API_PAGE_SIZE`、`API_RETRY_MAX`)
+- 输出目录(可选):`EXPORT_ROOT`、`LOG_ROOT`、`FETCH_ROOT`/`JSON_FETCH_ROOT`
+
+**安全提示**:建议将数据库/Token 等凭证保存在 `.env` 或受控秘钥管理中,生产环境使用最小权限账号。
+
+### 推荐定时方式 A(两段定时,更清晰)
+1) **更新 ODS(在线抓取 + 入库,FULL)**
```bash
- # 运行默认任务集
- python -m cli.main
-
- # 按需选择任务(逗号分隔)
- python -m cli.main --tasks ODS_ORDER_SETTLE,ORDERS,PAYMENTS
-
- # Dry-run 示例(不提交事务)
- python -m cli.main --tasks ORDERS --dry-run
-
- # Windows 批处理
- ..\\run_etl.bat --tasks PAYMENTS
+ python -m cli.main \
+ --pipeline-flow FULL \
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID" \
+ --api-token "$API_TOKEN"
+ ```
+2) **ODS → DWD(将新增/变更同步到 DWD)**
+ ```bash
+ python -m cli.main \
+ --pipeline-flow INGEST_ONLY \
+ --tasks DWD_LOAD_FROM_ODS \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID"
```
-5. **查看输出**:日志目录与导出目录分别由 `LOG_ROOT`、`EXPORT_ROOT` 控制;运行追踪与游标记录写入数据库 `etl_admin.*` 表。
-## 数据与运行流转
-- CLI 解析参数 → `AppConfig.load()` 组装配置 → `ETLScheduler` 创建 DB/API/游标/运行追踪器。
-- 调度器按任务代码实例化任务,读取/推进游标,落盘运行记录。
-- 任务模板:确定时间窗口 → 调用 API/ODS 数据 → 解析校验 → Loader 批量 Upsert/SCD2 → 质量检查 → 提交事务并回写游标。
+### 推荐定时方式 B(一条命令串起来)
+同一条命令先跑在线抓取/入库任务,再跑 DWD 装载任务:
+```bash
+python -m cli.main \
+ --pipeline-flow FULL \
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER,DWD_LOAD_FROM_ODS \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID" \
+ --api-token "$API_TOKEN"
+```
-## 测试与回放
-- 单元/集成测试:`pytest` 或 `python scripts/run_tests.py --suite online`。
-- 预置组合:`python scripts/run_tests.py --preset offline_realdb`(见 `scripts/test_presets.py`)。
-- 离线模式:`TEST_MODE=OFFLINE TEST_JSON_ARCHIVE_DIR=... pytest tests/unit/test_etl_tasks_offline.py`。
-- 数据库连通性:`python scripts/test_db_connection.py --dsn postgresql://... --query "SELECT 1"`。
+### `pipeline-flow` 说明
+- `FULL`:在线抓取落盘 + 本地清洗入库(ODS 任务会走抓取;`DWD_LOAD_FROM_ODS` 仅走入库阶段)
+- `FETCH_ONLY`:仅在线抓取落盘,不入库
+- `INGEST_ONLY`:仅从本地 JSON 回放入库(适合离线回放/补跑)
-## 其他提示
-- `.env.example` 列出了所有常用配置;`config/defaults.py` 记录默认值与任务窗口配置。
-- `loaders/ods/generic.py` 支持定义主键/列名即可落 ODS;`tasks/manual_ingest_task.py` 可将归档 JSON 快速灌入对应 ODS 表。
-- 需要新增任务时,在 `tasks/` 中实现并在 `orchestration/task_registry.py` 注册即可复用调度能力。
+## 目录结构与关键文件
+- 仓库根目录:`etl_billiards/` 主代码;`app/` 示例 runner;`开发笔记/` 项目笔记;`tmp/` 草稿/调试归档;`requirements.txt`(仓库根)依赖;`run_etl.sh/.bat` 启动脚本。
+ - 注意:根目录的 `run_etl.sh/.bat` 运行时要求当前目录为 `etl_billiards/`(因为入口是 `python -m cli.main`)。
+- `etl_billiards/`(主代码目录)
+ - `.env`:本地配置文件(可选,用环境变量也可)
+ - `cli/`:CLI 入口(`cli/main.py`)
+ - `config/`:`defaults.py` 默认值;`env_parser.py` 解析 `.env`/环境变量;`settings.py` AppConfig 加载/校验
+ - `api/`:`client.py` HTTP 请求、重试、分页与落盘
+ - `database/`:`connection.py` 连接封装;`operations.py` 批量 upsert;DDL:`schema_ODS_doc.sql`、`schema_dwd_doc.sql`
+ - `tasks/`:业务任务(ODS 抓取/回放、DWD 装载、质检等)
+ - `loaders/`:ODS/DWD/SCD2 Loader 实现
+ - `scd/`:`scd2_handler.py`(维度 SCD2 历史)
+ - `quality/`:质量检查器(行数/金额对照)
+ - `orchestration/`:`scheduler.py` 调度;`task_registry.py` 注册;`cursor_manager.py` 水位管理;`run_tracker.py` 运行记录
+ - `scripts/`:重建/测试/探活工具
+ - `docs/`:映射/样例/质检说明文档
+ - `fetch-test/`:接口联调/规则验证的一次性脚本与报告(不影响主流程)
+ - `reports/`:质检输出(如 `dwd_quality_report.json`)
+ - `tests/`:单元/集成测试
+## 项目文件索引(维护/AI 快速定位)
+> 说明:用于维护/AI 快速定位文件路径与用途;默认不列出 `.git/`、`__pycache__/`、`.pytest_cache/`、`*.pyc` 等自动生成内容。
+
+### /
+- `.gitignore`:Git 忽略规则。
+- `.gitkeep`:占位文件(用于保留空目录)。
+- `README.md`:项目总览与使用说明(本文档)。
+- `requirements.txt`:仓库根依赖清单(不含版本约束,建议优先用 `etl_billiards/requirements.txt`)。
+- `run_etl.bat`:Windows 启动脚本(需先 `cd etl_billiards`;入口为 `python -m cli.main`)。
+- `run_etl.sh`:Linux/macOS 启动脚本(需先 `cd etl_billiards`;会加载当前目录 `.env`)。
+
+### app/
+
+### etl_billiards/
+- `etl_billiards/.env`:本地运行环境变量(含敏感信息,勿提交/勿外传)。
+- `etl_billiards/__init__.py`:Python 包标记文件。
+- `etl_billiards/ods_row_report.json`:ODS 行数对照报告(source json vs ODS 表)。
+- `etl_billiards/requirements.txt`:ETL 运行依赖(带最低版本约束)。
+- `etl_billiards/run_ods.bat`:Windows 一键脚本:重建 ODS 并灌入示例 JSON。
+- `etl_billiards/setup.py`:打包/安装脚本(当前项目主要按“`cd etl_billiards; python -m cli.main`”方式运行)。
+
+### etl_billiards/api/
+- `etl_billiards/api/__init__.py`:Python 包标记文件。
+- `etl_billiards/api/client.py`:API客户端:统一封装 POST/重试/分页与列表提取逻辑。
+- `etl_billiards/api/endpoint_routing.py`:“近期记录 / 历史记录(Former)”接口路由规则。
+- `etl_billiards/api/local_json_client.py`:本地 JSON 客户端,模拟 APIClient 的分页接口,从落盘的 JSON 回放数据。
+- `etl_billiards/api/recording_client.py`:包装 APIClient,将分页响应落盘便于后续本地清洗。
+
+### etl_billiards/cli/
+- `etl_billiards/cli/__init__.py`:Python 包标记文件。
+- `etl_billiards/cli/main.py`:CLI主入口
+
+### etl_billiards/config/
+- `etl_billiards/config/__init__.py`:Python 包标记文件。
+- `etl_billiards/config/defaults.py`:配置默认值定义
+- `etl_billiards/config/env_parser.py`:环境变量解析
+- `etl_billiards/config/settings.py`:配置管理主类
+
+### etl_billiards/database/
+- `etl_billiards/database/__init__.py`:Python 包标记文件。
+- `etl_billiards/database/base.py`:数据库操作(批量、RETURNING支持)
+- `etl_billiards/database/connection.py`:Database connection manager with capped connect_timeout.
+- `etl_billiards/database/operations.py`:数据库批量操作
+- `etl_billiards/database/schema_dwd_doc.sql`:DWD Schema DDL(含字段/注释/口径说明)。
+- `etl_billiards/database/schema_etl_admin.sql`:etl_admin 元数据 Schema DDL(任务/水位/运行记录等)。
+- `etl_billiards/database/schema_ODS_doc.sql`:ODS Schema DDL(含字段/注释/口径说明)。
+- `etl_billiards/database/seed_ods_tasks.sql`:SQL 种子脚本:初始化/注册 ODS 任务。
+- `etl_billiards/database/seed_scheduler_tasks.sql`:SQL 种子脚本:初始化调度任务配置。
+
+### etl_billiards/database/Deleded & backup/
+- (本目录无直接文件)
+
+### etl_billiards/docs/
+- `etl_billiards/docs/dwd_main_tables_dictionary.md`:DWD 主表(非 Ex)表格说明书
+- `etl_billiards/docs/在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。.md`:在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。
+
+### etl_billiards/fetch-test/
+- `etl_billiards/fetch-test/compare_recent_former_endpoints.py`:对比“近期记录”与“历史记录(Former)”接口:
+- `etl_billiards/fetch-test/README.md`:fetch-test
+- `etl_billiards/fetch-test/recent_vs_former_report.json`:报告/比对输出(JSON)。
+- `etl_billiards/fetch-test/recent_vs_former_report.md`:近期记录 vs 历史记录(Former) 接口对比报告
+
+### etl_billiards/loaders/
+- `etl_billiards/loaders/__init__.py`:Python 包标记文件。
+- `etl_billiards/loaders/base_loader.py`:数据加载器基类
+
+### etl_billiards/loaders/dimensions/
+- `etl_billiards/loaders/dimensions/__init__.py`:Python 包标记文件。
+- `etl_billiards/loaders/dimensions/assistant.py`:助教维度加载器
+- `etl_billiards/loaders/dimensions/member.py`:会员维度表加载器
+- `etl_billiards/loaders/dimensions/package.py`:团购/套餐定义加载器
+- `etl_billiards/loaders/dimensions/product.py`:商品维度 + 价格SCD2 加载器
+- `etl_billiards/loaders/dimensions/table.py`:台桌维度加载器
+
+### etl_billiards/loaders/facts/
+- `etl_billiards/loaders/facts/__init__.py`:Python 包标记文件。
+- `etl_billiards/loaders/facts/assistant_abolish.py`:助教作废事实表
+- `etl_billiards/loaders/facts/assistant_ledger.py`:助教流水事实表
+- `etl_billiards/loaders/facts/coupon_usage.py`:券核销事实表
+- `etl_billiards/loaders/facts/inventory_change.py`:库存变动事实表
+- `etl_billiards/loaders/facts/order.py`:订单事实表加载器
+- `etl_billiards/loaders/facts/payment.py`:支付事实表加载器
+- `etl_billiards/loaders/facts/refund.py`:退款事实表加载器
+- `etl_billiards/loaders/facts/table_discount.py`:台费打折事实表
+- `etl_billiards/loaders/facts/ticket.py`:小票详情加载器
+- `etl_billiards/loaders/facts/topup.py`:充值记录事实表
+
+### etl_billiards/loaders/ods/
+- `etl_billiards/loaders/ods/__init__.py`:Python 包标记文件。
+- `etl_billiards/loaders/ods/generic.py`:Generic ODS loader that keeps raw payload + primary keys.
+
+### etl_billiards/models/
+- `etl_billiards/models/__init__.py`:Python 包标记文件。
+- `etl_billiards/models/parsers.py`:数据类型解析器
+- `etl_billiards/models/validators.py`:数据验证器
+
+### etl_billiards/orchestration/
+- `etl_billiards/orchestration/__init__.py`:Python 包标记文件。
+- `etl_billiards/orchestration/cursor_manager.py`:游标管理器
+- `etl_billiards/orchestration/run_tracker.py`:运行记录追踪器
+- `etl_billiards/orchestration/scheduler.py`:ETL 调度:支持在线抓取、离线清洗入库、全流程三种模式。
+- `etl_billiards/orchestration/task_registry.py`:任务注册表
+
+### etl_billiards/quality/
+- `etl_billiards/quality/__init__.py`:Python 包标记文件。
+- `etl_billiards/quality/balance_checker.py`:余额一致性检查器
+- `etl_billiards/quality/base_checker.py`:数据质量检查器基类
+
+### etl_billiards/reports/
+- `etl_billiards/reports/dwd_quality_report.json`:DWD 质量核对输出(行数/金额对照)。
+
+### etl_billiards/scd/
+- `etl_billiards/scd/__init__.py`:Python 包标记文件。
+- `etl_billiards/scd/scd2_handler.py`:SCD2 (Slowly Changing Dimension Type 2) 处理逻辑
+
+### etl_billiards/scripts/
+- `etl_billiards/scripts/bootstrap_schema.py`:Apply the PRD-aligned warehouse schema (ODS/DWD/DWS) to PostgreSQL.
+- `etl_billiards/scripts/build_dwd_from_ods.py`:Populate PRD DWD tables from ODS payload snapshots.
+- `etl_billiards/scripts/build_dws_order_summary.py`:Recompute billiards_dws.dws_order_summary from DWD fact tables.
+- `etl_billiards/scripts/check_ods_json_vs_table.py`:ODS JSON 字段核对脚本:对照当前数据库中的 ODS 表字段,检查示例 JSON(默认目录 export/test-json-doc)
+- `etl_billiards/scripts/check_ods_gaps.py`:ODS 缺失校验脚本:API 主键 vs ODS 主键逐条比对,输出缺失明细样例。
+- `etl_billiards/scripts/reload_ods_windowed.py`:ODS 窗口化补跑脚本:按时间切片重跑 ODS 任务,并可配置窗口粒度与延时。
+- `etl_billiards/scripts/rebuild_db_and_run_ods_to_dwd.py`:一键重建 ETL 相关 Schema,并执行 ODS → DWD。
+- `etl_billiards/scripts/rebuild_ods_from_json.py`:从本地 JSON 示例目录重建 billiards_ods.* 表,并导入样例数据。
+- `etl_billiards/scripts/run_tests.py`:灵活的测试执行脚本,可像搭积木一样组合不同参数或预置命令(模式/数据库/归档路径等),
+- `etl_billiards/scripts/test_db_connection.py`:Quick utility for validating PostgreSQL connectivity (ASCII-only output).
+- `etl_billiards/scripts/test_presets.py`:测试命令仓库:集中维护 run_tests.py 的常用组合,支持一键执行。
+
+### etl_billiards/scripts/Deleded & backup/
+- (本目录无直接文件)
+
+### etl_billiards/tasks/
+- `etl_billiards/tasks/__init__.py`:Python 包标记文件。
+- `etl_billiards/tasks/assistant_abolish_task.py`:助教作废任务
+- `etl_billiards/tasks/assistants_task.py`:助教账号任务
+- `etl_billiards/tasks/base_dwd_task.py`:DWD任务基类
+- `etl_billiards/tasks/base_task.py`:ETL任务基类(引入 Extract/Transform/Load 模板方法)
+- `etl_billiards/tasks/coupon_usage_task.py`:平台券核销任务
+- `etl_billiards/tasks/dwd_load_task.py`:DWD 装载任务:从 ODS 增量写入 DWD(维度 SCD2,事实按时间增量)。
+- `etl_billiards/tasks/dwd_quality_task.py`:DWD 质量核对任务:按 dwd_quality_check.md 输出行数/金额对照报表。
+- `etl_billiards/tasks/init_dwd_schema_task.py`:初始化 DWD Schema:执行 schema_dwd_doc.sql,可选先 DROP SCHEMA。
+- `etl_billiards/tasks/init_schema_task.py`:任务:初始化运行环境,执行 ODS 与 etl_admin 的 DDL,并准备日志/导出目录。
+- `etl_billiards/tasks/inventory_change_task.py`:库存变更任务
+- `etl_billiards/tasks/ledger_task.py`:助教流水任务
+- `etl_billiards/tasks/manual_ingest_task.py`:手工示例数据灌入:按 schema_ODS_doc.sql 的表结构写入 ODS。
+- `etl_billiards/tasks/members_dwd_task.py`:DWD Task:Process Member Records from ODS to Dimension Table.
+- `etl_billiards/tasks/members_task.py`:会员ETL任务
+- `etl_billiards/tasks/ods_json_archive_task.py`:在线抓取 ODS 相关接口并落盘为 JSON(用于后续离线回放/入库)。
+- `etl_billiards/tasks/ods_tasks.py`:ODS ingestion tasks.
+- `etl_billiards/tasks/orders_task.py`:订单ETL任务
+- `etl_billiards/tasks/packages_task.py`:团购/套餐定义任务
+- `etl_billiards/tasks/payments_dwd_task.py`:DWD Task:Process Payment Records from ODS to Fact Table.
+- `etl_billiards/tasks/payments_task.py`:支付记录ETL任务
+- `etl_billiards/tasks/products_task.py`:商品档案(PRODUCTS)ETL任务
+- `etl_billiards/tasks/refunds_task.py`:退款记录任务
+- `etl_billiards/tasks/table_discount_task.py`:台费折扣任务
+- `etl_billiards/tasks/tables_task.py`:台桌档案任务
+- `etl_billiards/tasks/ticket_dwd_task.py`:DWD Task:Process Ticket Details from ODS to DWD fact tables.
+- `etl_billiards/tasks/topups_task.py`:充值记录任务
+
+### etl_billiards/tasks/dwd/
+- (本目录无直接文件)
+
+### etl_billiards/tests/
+- `etl_billiards/tests/__init__.py`:Python 包标记文件。
+
+### etl_billiards/tests/integration/
+- `etl_billiards/tests/integration/__init__.py`:Python 包标记文件。
+- `etl_billiards/tests/integration/test_database.py`:数据库集成测试
+
+### etl_billiards/tests/unit/
+- `etl_billiards/tests/unit/__init__.py`:Python 包标记文件。
+- `etl_billiards/tests/unit/task_test_utils.py`:ETL 任务测试的共用辅助模块,涵盖在线/离线模式所需的伪造数据、客户端与配置等工具函数。
+- `etl_billiards/tests/unit/test_config.py`:配置管理测试
+- `etl_billiards/tests/unit/test_endpoint_routing.py`:Unit tests for recent/former endpoint routing.
+- `etl_billiards/tests/unit/test_etl_tasks_offline.py`:离线模式任务测试,通过回放归档 JSON 来验证 T+L 链路可用。
+- `etl_billiards/tests/unit/test_etl_tasks_online.py`:在线模式下的端到端任务测试,验证所有任务在模拟 API 下能顺利执行。
+- `etl_billiards/tests/unit/test_etl_tasks_stages.py`:验证 14 个任务的 E/T/L 分阶段调用(FakeDB/FakeAPI,不访问真实接口或数据库)。
+- `etl_billiards/tests/unit/test_ods_tasks.py`:Unit tests for the new ODS ingestion tasks.
+- `etl_billiards/tests/unit/test_parsers.py`:解析器测试
+- `etl_billiards/tests/unit/test_reporting.py`:汇总与报告工具的单测。
+
+### etl_billiards/utils/
+- `etl_billiards/utils/__init__.py`:Python 包标记文件。
+- `etl_billiards/utils/helpers.py`:通用工具函数
+- `etl_billiards/utils/json_store.py`:JSON 归档/读取的通用工具。
+- `etl_billiards/utils/reporting.py`:简单的任务结果汇总与格式化工具。
+
+### tmp/
+- `tmp/20251121-task.txt`:历史任务/计划记录(可能存在编码问题)。
+- `tmp/doc_extracted.txt`:从 DWD 文档抽取的正文(大文本)。
+- `tmp/doc_lines.txt`:DWD 文档按行抽取/对照(文本)。
+- `tmp/dwd_tables.json`:DWD 表清单(JSON)。
+- `tmp/dwd_tables_full.json`:DWD 表清单(完整版 JSON)。
+- `tmp/hebing.py`:临时脚本:按“同名 key”合并目录内 md+json 输出 merged_output.txt。
+- `tmp/README_FULL.md`:历史/草稿:README 详细版(已合并进根 README)。
+- `tmp/rebuild_run_20251214-042115.log`:运行日志/调试输出(临时文件)。
+- `tmp/rewrite_schema_dwd_doc_comments.py`:临时脚本:批量重写 DWD DDL 注释(归档/草稿)。
+- `tmp/rewrite_schema_ods_doc_comments.py`:临时脚本:批量重写 ODS DDL 注释(归档/草稿)。
+- `tmp/schema_dwd.sql`:DWD schema 草稿/导出(归档)。
+- `tmp/schema_dwd_doc.sql`:DWD schema doc 版本(归档)。
+- `tmp/schema_ODS_doc copy.sql`:ODS schema doc 备份(归档)。
+- `tmp/schema_ODS_doc.sql`:ODS schema doc 版本(归档)。
+- `tmp/temp_chinese.txt`:编码/文本对照测试。
+- `tmp/tmp_debug_sql.py`:临时脚本:调试 SQL/映射(归档)。
+- `tmp/tmp_drop_dwd.py`:临时脚本:DROP SCHEMA billiards_dwd(危险,勿在生产执行)。
+- `tmp/tmp_dwd_tasks.py`:临时脚本:调试 DWD 相关任务(归档)。
+- `tmp/tmp_problems.py`:临时脚本:问题排查记录/复现(归档)。
+- `tmp/tmp_run_sql.py`:临时脚本:拼接/执行一条 INSERT...SELECT 验证映射(需 PG_DSN)。
+- `tmp/非球接口API.md`:上游接口笔记/汇总(草稿/归档)。
+
+### tmp/a/
+- (本目录无直接文件)
+
+### tmp/b/
+- (本目录无直接文件)
+
+### tmp/etl_billiards_misc/
+- `tmp/etl_billiards_misc/0.py`:Simple PostgreSQL connectivity smoke-checker.
+- `tmp/etl_billiards_misc/feiqiu-ETL.code-workspace`:VS Code workspace 文件(归档)。
+- `tmp/etl_billiards_misc/草稿.txt`:草稿/说明(归档)。
+
+### tmp/etl_billiards_misc/backups/
+- `tmp/etl_billiards_misc/backups/manual_ingest_task.py`:历史版本备份(归档)。
+- `tmp/etl_billiards_misc/backups/manual_ingest_task.py.bak_20251209`:历史版本备份(归档)。
+- `tmp/etl_billiards_misc/backups/schema_ODS_doc.sql`:历史版本备份(归档)。
+- `tmp/etl_billiards_misc/backups/schema_ODS_doc.sql.bak_20251209`:历史版本备份(归档)。
+
+### tmp/etl_billiards_misc/tmp & Delete/
+- `tmp/etl_billiards_misc/tmp & Delete/.env.example`:旧示例配置(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/dwd_schema_columns.txt`:DWD 字段提取/对照文本(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/DWD层设计建议.docx`:DWD 设计建议文档(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/DWD层设计草稿.md`:DWD 设计草稿(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/schema_dwd_doc.sql.bak`:schema 备份(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.bak`:schema 备份(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.rewrite2.bak`:schema 重写过程备份(归档)。
+- `tmp/etl_billiards_misc/tmp & Delete/schema_v2.sql`:schema v2 草稿(归档)。
+
+### tmp/recharge_only/
+- `tmp/recharge_only/recharge_settlements.json`:离线样例 JSON(仅充值结算)。
+
+### tmp/single_ingest/
+- `tmp/single_ingest/goods_stock_movements.json`:离线最小样例 JSON(单文件)。
+
+### 开发笔记/
+- `开发笔记/记录.md`:开发/迁移过程的备忘与待办(归档)。
+
+## 架构与流程
+执行链路(控制流):
+1) CLI(`cli/main.py`)解析参数 → 生成 AppConfig → 初始化日志/DB/API;
+2) 调度层(`orchestration/scheduler.py`)按 `task_registry.py` 实例化任务,设置 run_uuid、cursor(水位)、上下文;
+3) 任务执行模板:获取时间窗口/水位(`cursor_manager.py`)→ Extract(API 分页/重试或离线读 JSON)→ Transform(解析/校验)→ Load(Loader 批量 upsert/SCD2/增量写入,底层 `database/operations.py`)→(可选)质量检查 → 更新水位与运行记录(`run_tracker.py`),提交/回滚事务。
+
+数据流与依赖:
+- 配置:`config/defaults.py` + `.env`/环境变量 + CLI 参数叠加
+- 在线:`api/client.py` 支撑分页/重试;可落盘 JSON(`pipeline.fetch_root`)
+- 离线:`manual_ingest_task.py` 从 `INGEST_SOURCE_DIR` 回放入库
+- DWD:`dwd_load_task.py` 依据 `TABLE_MAP/FACT_MAPPINGS` 映射装载,维度走 SCD2,事实走增量
+- 质检:`dwd_quality_task.py` 输出 `reports/dwd_quality_report.json`
+
+## ODS → DWD 策略与建模要点
+1) ODS 留底:保留源主键、payload、时间/来源信息,便于回溯。
+2) DWD 清洗:维度走 SCD2,事实按时间/水位增量;字段类型、单位、枚举标准化,同时保留溯源字段。
+3) 颗粒一致:一张 DWD 表只承载一种业务事件/颗粒,避免混颗粒。
+4) 业务键统一:site_id、member_id、table_id、order_settle_id、order_trade_no 等统一命名。
+5) 不过度汇总:DWD 只做明细/轻度清洗,聚合留到 DWS/报表。
+6) 去嵌套:数组展开为子表/子行,重复 profile 提炼为维度。
+7) 长期演进:优先加列/加表,减少对已有表结构的破坏。
+
+## 常用 CLI
+```bash
+cd etl_billiards
+
+# 运行 defaults.py 中的默认任务列表(在线 FULL 流程)
+python -m cli.main --pg-dsn "$PG_DSN" --store-id "$STORE_ID" --api-token "$API_TOKEN"
+
+# 运行指定任务
+python -m cli.main --tasks INIT_ODS_SCHEMA,MANUAL_INGEST --pipeline-flow INGEST_ONLY --ingest-source "../tmp/single_ingest"
+
+# 覆盖 DSN / API / 输出目录
+python -m cli.main --pg-dsn "postgresql://user:pwd@host:5432/db" --store-id 123 --api-token "..." --fetch-root "./json_fetch"
+
+# 试运行(不写库)
+python -m cli.main --dry-run --tasks DWD_LOAD_FROM_ODS
+```
+
+## 窗口切分与补偿
+用于 ETL 任务、ODS 缺失校验、数据一致性检查等“带时间窗口”的执行场景。逻辑如下:
+- 仅当传入窗口参数(如 CLI `--window-start/--window-end` 或脚本 `--start/--end`)时启用切分。
+- 先对整体窗口前后补偿 N 小时,再按月切分(`month` 为最大单位)。不需要切分时设为 `none`。
+- 分段窗口将依次执行并汇总结果。
+
+配置项(默认值见 `config/defaults.py`):
+- `run.window_split.unit`:`month` / `none`(默认 `month`)
+- `run.window_split.compensation_hours`:整数小时(默认 2)
+
+环境变量:
+- `WINDOW_SPLIT_UNIT`
+- `WINDOW_COMPENSATION_HOURS`
+
+CLI 参数(覆盖配置):
+- `python -m cli.main`:`--window-split-unit`,`--window-compensation-hours`
+- `scripts/check_ods_gaps.py`:`--window-split-unit`,`--window-compensation-hours`
+- `scripts/check_data_integrity.py`:`--window-split-unit`,`--window-compensation-hours`
+- `scripts/reload_ods_windowed.py`:`--window-split-unit`,`--window-compensation-hours`
+
+示例(`unit=month`,`compensation_hours=2`):
+- 传入窗口:`2025/11/10 10:00` - `2026/1/19 10:15`
+- 实际处理窗口切分:
+ - `2025/11/10 08:00` - `2025/12/01 00:00`
+ - `2025/12/01 00:00` - `2026/01/01 00:00`
+ - `2026/01/01 00:00` - `2026/01/19 12:15`
+
+## 测试
+说明:仓库未固定 pytest 版本(运行测试需自行安装 `pytest`)。
+
+```bash
+cd etl_billiards
+pip install pytest
+
+# 单元测试(模拟 API + FakeDB)
+pytest tests/unit
+
+# 集成测试(需要设置 TEST_DB_DSN)
+TEST_DB_DSN="postgresql://user:pwd@host:5432/db" pytest tests/integration/test_database.py
+
+# 便捷测试执行器(可选)
+python scripts/run_tests.py --suite online -k ORDERS
+python scripts/test_db_connection.py --dsn "postgresql://user:pwd@host:5432/db" --query "SELECT 1"
+```
+
+## 开发与扩展
+- 新任务:在 `tasks/` 继承 BaseTask,实现 `get_task_code/execute`,并在 `orchestration/task_registry.py` 注册。
+- 新 Loader/Checker:参考 `loaders/`、`quality/`,复用批量 upsert/质检接口。
+- 新配置项:在 `config/defaults.py` 增加默认值,并在 `config/env_parser.py` 增加环境变量映射(如需要)。
+
+## ODS 任务上线指引
+- 元数据/任务注册脚本:
+ - `etl_billiards/database/seed_ods_tasks.sql`
+ - `etl_billiards/database/seed_scheduler_tasks.sql`
+- 确认 `etl_admin.etl_task` 中已启用所需任务(不同环境需替换 store_id / schema)。
+- 离线回放/重建 ODS(开发/运维):
+ ```bash
+ cd etl_billiards
+ python scripts/rebuild_ods_from_json.py --dsn "$PG_DSN" --json-dir "export/test-json-doc"
+ ```
+
+## ODS 表概览(数据路径)
+| ODS 表名 | 接口 Path | 数据列表路径 |
+| ---------------------------------- | ------------------------------------------------- | ----------------------------- |
+| assistant_accounts_master | /PersonnelManagement/SearchAssistantInfo | data.assistantInfos |
+| assistant_service_records | /AssistantPerformance/GetOrderAssistantDetails | data.orderAssistantDetails |
+| assistant_cancellation_records | /AssistantPerformance/GetAbolitionAssistant | data.abolitionAssistants |
+| goods_stock_movements | /GoodsStockManage/QueryGoodsOutboundReceipt | data.queryDeliveryRecordsList |
+| goods_stock_summary | /TenantGoods/GetGoodsStockReport | data |
+| group_buy_packages | /PackageCoupon/QueryPackageCouponList | data.packageCouponList |
+| group_buy_redemption_records | /Site/GetSiteTableUseDetails | data.siteTableUseDetailsList |
+| member_profiles | /MemberProfile/GetTenantMemberList | data.tenantMemberInfos |
+| member_balance_changes | /MemberProfile/GetMemberCardBalanceChange | data.tenantMemberCardLogs |
+| member_stored_value_cards | /MemberProfile/GetTenantMemberCardList | data.tenantMemberCards |
+| payment_transactions | /PayLog/GetPayLogListPage | data |
+| platform_coupon_redemption_records | /Promotion/GetOfflineCouponConsumePageList | data |
+| recharge_settlements | /Site/GetRechargeSettleList | data.settleList |
+| refund_transactions | /Order/GetRefundPayLogList | data |
+| settlement_records | /Site/GetAllOrderSettleList | data.settleList |
+| settlement_ticket_details | /Order/GetOrderSettleTicketNew | 完整 JSON |
+| site_tables_master | /Table/GetSiteTables | data.siteTables |
+| stock_goods_category_tree | /TenantGoodsCategory/QueryPrimarySecondaryCategory| data.goodsCategoryList |
+| store_goods_master | /TenantGoods/GetGoodsInventoryList | data.orderGoodsList |
+| store_goods_sales_records | /TenantGoods/GetGoodsSalesList | data.orderGoodsLedgers |
+| table_fee_discount_records | /Site/GetTaiFeeAdjustList | data.taiFeeAdjustInfos |
+| table_fee_transactions | /Site/GetSiteTableOrderDetails | data.siteTableUseDetailsList |
+| tenant_goods_master | /TenantGoods/QueryTenantGoods | data.tenantGoodsList |
+
+> 完整字段级映射见 `etl_billiards/docs/` 与 ODS/DWD DDL。
+
+## 当前状态(2025-12-09)
+- 示例 JSON 已全量灌入,DWD 行数与 ODS 对齐。
+- 分类维度已展平大类+子类:`dim_goods_category` 26 行(category_level/leaf 已赋值)。
+- 部分空字段源数据即为空,如需补值请先确认上游。
+
+## 可精简/归档
+- `tmp/`、`tmp/etl_billiards_misc/` 中草稿、旧备份、调试脚本仅供参考,不影响运行。
+- 根级保留必要文件(README、requirements、run_etl.*),其余临时文件按需归档至 `tmp/`。
+
+## 一键更新(推荐)
+
+日常需要把数据从 ODS 更新到最新,并同步刷新 DWD/DWS 时,直接运行一键脚本:
+
+```bash
+cd etl_billiards
+python run_update.py
+```
+
+常用参数:
+- `--overlap-seconds 3600`:冗余抓取窗口(默认 3600 秒)
+- `--dws-rebuild-days 1`:DWS 回算冗余天数(默认 1 天)
+- `--dws-start YYYY-MM-DD --dws-end YYYY-MM-DD`:手工指定 DWS 回算日期范围
+- `--skip-ods`:跳过 ODS 在线抓取(仅跑 DWD/DWS)
+- `--ods-tasks ODS_PAYMENT,ODS_TABLE_USE,...`:只跑指定 ODS 任务
+- `--check-ods-gaps`:在 ODS 更新完成后执行缺失校验(API 主键 vs ODS 主键)
+- `--check-ods-overlap-hours 24`:缺失校验时,从 ODS 最新截止时间回溯的小时数(默认 24)
+- `--check-ods-window-days 1`:缺失校验 API 窗口粒度(默认 1 天)
+- `--check-ods-page-size 200`:缺失校验 API 每页大小(默认 200)
+- `--check-ods-timeout-sec 1800`:缺失校验步骤超时秒数(默认 1800)
+- `--check-ods-task-codes ODS_PAYMENT,ODS_TABLE_USE,...`:仅校验指定 ODS 任务
+
+### ODS 缺失校验(API vs ODS)
+
+说明:
+- 校验口径为 ODS 表 `MAX(fetched_at)` 的最小值,视为“最新一致截止时间”。
+- `--from-cutoff` 会从该截止时间回溯 N 小时(默认 24 小时)到当前,便于日常增量校验。
+
+全量校验(从 2025-07 至今):
+```bash
+cd etl_billiards
+python scripts/check_ods_gaps.py --start 2025-07-01
+```
+
+更新时校验(从 ODS 最新截止时间回溯 24h):
+```bash
+cd etl_billiards
+python run_update.py --check-ods-gaps
+```
+
+## FAQ
+- 字段空值:若映射已存在且源列非空仍为空,再检查上游 JSON;维度 SCD2 按全量合并。
+- DSN/路径:确认 `PG_DSN`、`STORE_ID`、`INGEST_SOURCE_DIR` 与本地一致。
+- 新增任务:在 `tasks/` 实现并注册到 `task_registry.py`,必要时同步更新 DDL 与映射。
+- 权限/运行:检查网络、账号权限;脚本需执行权限(如 `chmod +x run_etl.sh`)。
+
+---
+
+## Cutoff(截止时间)检查
+
+当你需要“上次数据截止到什么时候”“现在应该从哪里开始补跑”时,使用任务 `CHECK_CUTOFF`:
+
+```bash
+cd etl_billiards
+python -m cli.main --pipeline-flow INGEST_ONLY --tasks CHECK_CUTOFF
+```
+
+它会输出:
+- `etl_admin.etl_cursor`:每个任务的 `last_start/last_end/last_run_id`(调度游标)
+- ODS:对 `DWD_LOAD_FROM_ODS` 依赖的各个 `billiards_ods.*` 表做 `MAX(fetched_at)`(真实已入库 ODS 的截止)
+- DWD/DWS:输出若干关键表的最大业务时间/最大更新时刻,便于快速核对
+
+> 如果 `etl_cursor.last_end` 很新,但 ODS 的 `MAX(fetched_at)` 很旧,通常表示在线抓取没跑通(最常见是 `API_TOKEN` 过期导致 401)。
+
+## 冗余抓取方案(推荐)
+
+为避免边界时间丢数(上游延迟写入、接口分页抖动、窗口切换等),建议在 cutoff 基础上向前追加 **1 小时** 冗余量:
+
+- 配置:将 `OVERLAP_SECONDS` 设为 3600(默认 120 秒)
+
+```env
+# etl_billiards/.env
+OVERLAP_SECONDS=3600
+```
+
+冗余方案的关键点是“重抓不重落”,依靠各层的去重/幂等机制只落新数据:
+- **ODS 层**:主键/冲突列 UPSERT(重复抓取只会 upsert,不会重复插入)
+- **DWD 层**:事实表增量插入 + 主键冲突不重复落(重复范围会被跳过),维度表按 SCD2 合并
+- **DWS 层**:对指定日期窗口先 delete 再 upsert(窗口内重算幂等)
+
+> 如果你希望“冗余窗口内的数据发生变更也要覆盖更新”,需要把对应层的冲突策略从 `DO NOTHING` 调整为 `DO UPDATE`(当前实现以“只落新数据”为主)。
+
+## DWS(汇总层)入库
+
+本项目已包含 `billiards_dws` 汇总层(当前提供 `dws_order_summary`):
+
+1) 初始化 DWS 表结构:
+
+```bash
+python -m cli.main --pipeline-flow INGEST_ONLY --tasks INIT_DWS_SCHEMA
+```
+
+2) 生成/刷新汇总表(按窗口重算,建议配合 `--window-start/--window-end`):
+
+```bash
+python -m cli.main --pipeline-flow INGEST_ONLY --tasks DWS_BUILD_ORDER_SUMMARY \
+ --window-start "2025-10-01 00:00:00" \
+ --window-end "2025-12-26 23:59:59"
+```
+
+3) 推荐串联(ODS -> DWD -> DWS):
+
+```bash
+# 先跑在线 ODS 抓取(需要有效 API_TOKEN;如果出现 401 请更新 token)
+python -m cli.main --pipeline-flow FULL --tasks ODS_MEMBER,ODS_PAYMENT,ODS_REFUND,ODS_SETTLEMENT_RECORDS
+
+# 再把 ODS 增量同步到 DWD
+python -m cli.main --pipeline-flow INGEST_ONLY --tasks DWD_LOAD_FROM_ODS
+
+# 最后重算 DWS
+python -m cli.main --pipeline-flow INGEST_ONLY --tasks DWS_BUILD_ORDER_SUMMARY
+```
+
+
+## 日志 (UTF-8)
+- 默认日志目录:`etl_billiards/logs/`
+- 每次运行都会生成一个带有时间戳的 `.log` 文件,以便于使用外部工具查看。
+常用选项:
+
+- `--log-file` 自定义日志路径(覆盖默认值)。
+- `--log-dir` 自定义日志目录。
+- `--log-level` 日志级别(`INFO`/`DEBUG`)。
+- `--no-log-console` 禁用控制台日志记录(仅写入文件)。
+
+示例(按月切分 + 前后补偿 2h):
+```bash
+cd etl_billiards
+python scripts/check_ods_gaps.py --start 2025-07-01 --end 2025-09-30 --window-split-unit month --window-compensation-hours 2 --task-codes ODS_PAYMENT --sleep-per-window-seconds 0.5
+python scripts/reload_ods_windowed.py --tasks ODS_PAYMENT,ODS_TABLE_USE --start 2025-07-01 --end 2025-09-30 --window-split-unit month --window-compensation-hours 2 --sleep-seconds 1
+python run_update.py --check-ods-gaps --check-ods-window-days 1 --check-ods-sleep-per-window-seconds 0.5
+```
diff --git a/Untitled b/Untitled
new file mode 100644
index 0000000..42061c0
--- /dev/null
+++ b/Untitled
@@ -0,0 +1 @@
+README.md
\ No newline at end of file
diff --git a/app/etl_busy.py b/app/etl_busy.py
deleted file mode 100644
index c493046..0000000
--- a/app/etl_busy.py
+++ /dev/null
@@ -1,9 +0,0 @@
-# app/etl_busy.py
-def run():
- """
- 忙时抓取逻辑。
- TODO: 这里写具体抓取流程(API 调用 / 网页解析 / 写入 PostgreSQL 等)
- """
- print("Running busy-period ETL...")
- # 示例:后续在这里接 PostgreSQL 或 HTTP 抓取
- # ...
\ No newline at end of file
diff --git a/app/etl_idle.py b/app/etl_idle.py
deleted file mode 100644
index 06a4ac5..0000000
--- a/app/etl_idle.py
+++ /dev/null
@@ -1,8 +0,0 @@
-# app/etl_idle.py
-def run():
- """
- 闲时抓取逻辑。
- 可以做全量同步、大批量历史修正等。
- """
- print("Running idle-period ETL...")
- # ...
\ No newline at end of file
diff --git a/app/runner.py b/app/runner.py
deleted file mode 100644
index e2abc25..0000000
--- a/app/runner.py
+++ /dev/null
@@ -1,31 +0,0 @@
-# app/runner.py
-import argparse
-from datetime import datetime
-
-from . import etl_busy, etl_idle
-
-
-def main():
- parser = argparse.ArgumentParser(description="Feiqiu ETL Runner")
- parser.add_argument(
- "--mode",
- choices=["busy", "idle"],
- required=True,
- help="ETL mode: busy or idle",
- )
-
- args = parser.parse_args()
- now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
-
- print(f"[{now}] Start ETL mode={args.mode}")
-
- if args.mode == "busy":
- etl_busy.run()
- else:
- etl_idle.run()
-
- print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] ETL finished.")
-
-
-if __name__ == "__main__":
- main()
\ No newline at end of file
diff --git a/etl_billiards/.env b/etl_billiards/.env
index 06bca67..75110ab 100644
--- a/etl_billiards/.env
+++ b/etl_billiards/.env
@@ -1,53 +1,132 @@
-# 数据库配置(真实库)
+# ==============================================================================
+# ETL 系统配置文件
+# ==============================================================================
+# 配置优先级:DEFAULTS < .env < CLI 参数
+
+# ------------------------------------------------------------------------------
+# 数据库配置
+# ------------------------------------------------------------------------------
+# 完整 DSN(优先使用,如果设置了则忽略下面的 host/port/name/user/password)
PG_DSN=postgresql://local-Python:Neo-local-1991125@100.64.0.4:5432/LLZQ-test
+
+# 分离式配置(如果不使用 DSN,可以单独配置以下参数)
+# PG_HOST=localhost
+# PG_PORT=5432
+# PG_NAME=your_database
+# PG_USER=your_user
+# PG_PASSWORD=your_password
+
+# 连接超时(秒,范围 1-20)
PG_CONNECT_TIMEOUT=10
-# 如需拆分配置:PG_HOST=... PG_PORT=... PG_NAME=... PG_USER=... PG_PASSWORD=...
-# API配置(如需走真实接口再填写)
-API_BASE=https://api.example.com
-API_TOKEN=your_token_here
-# API_TIMEOUT=20
-# API_PAGE_SIZE=200
-# API_RETRY_MAX=3
+# ------------------------------------------------------------------------------
+# 数据库 Schema 配置
+# ------------------------------------------------------------------------------
+# OLTP 业务数据 schema(默认 billiards)
+SCHEMA_OLTP=billiards
-# 应用配置
+# ETL 管理数据 schema(默认 etl_admin)
+SCHEMA_ETL=etl_admin
+
+# ------------------------------------------------------------------------------
+# API 配置
+# ------------------------------------------------------------------------------
+API_BASE=https://pc.ficoo.vip/apiprod/admin/v1/
+API_TOKEN=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGllbnQtdHlwZSI6IjQiLCJ1c2VyLXR5cGUiOiIxIiwiaHR0cDovL3NjaGVtYXMubWljcm9zb2Z0LmNvbS93cy8yMDA4LzA2L2lkZW50aXR5L2NsYWltcy9yb2xlIjoiMTIiLCJyb2xlLWlkIjoiMTIiLCJ0ZW5hbnQtaWQiOiIyNzkwNjgzMTYwNzA5OTU3Iiwibmlja25hbWUiOiLnp5_miLfnrqHnkIblkZjvvJrmganmgakxIiwic2l0ZS1pZCI6IjAiLCJtb2JpbGUiOiIxMzgxMDUwMjMwNCIsInNpZCI6IjI5NTA0ODk2NTgzOTU4NDUiLCJzdGFmZi1pZCI6IjMwMDk5MTg2OTE1NTkwNDUiLCJvcmctaWQiOiIwIiwicm9sZS10eXBlIjoiMyIsInJlZnJlc2hUb2tlbiI6Iks1ZnBhYlRTNkFsR0FpMmN4WGYrMHdJVkk0L2UvTVQrSVBHM3V5VWRrSjg9IiwicmVmcmVzaEV4cGlyeVRpbWUiOiIyMDI2LzEvMzEg5LiL5Y2IMTA6MTQ6NTEiLCJuZWVkQ2hlY2tUb2tlbiI6ImZhbHNlIiwiZXhwIjoxNzY5ODY4ODkxLCJpc3MiOiJ0ZXN0IiwiYXVkIjoiVXNlciJ9.BH3-iwwrBczb8aFfI__6kwe3AIsEPacN9TruaTrQ3nY
+
+# API 请求超时(秒)
+API_TIMEOUT=20
+
+# 分页大小
+API_PAGE_SIZE=200
+
+# 最大重试次数
+API_RETRY_MAX=3
+
+# 重试退避时间(JSON 数组格式,单位秒)
+# API_RETRY_BACKOFF=[1, 2, 4]
+
+# ------------------------------------------------------------------------------
+# 门店配置
+# ------------------------------------------------------------------------------
STORE_ID=2790685415443269
-# TIMEZONE=Asia/Taipei
-# SCHEMA_OLTP=billiards
-# SCHEMA_ETL=etl_admin
+TIMEZONE=Asia/Taipei
+# ------------------------------------------------------------------------------
# 路径配置
-EXPORT_ROOT=C:\dev\LLTQ\export\JSON
-LOG_ROOT=C:\dev\LLTQ\export\LOG
-FETCH_ROOT=
-INGEST_SOURCE_DIR=
-WRITE_PRETTY_JSON=false
-PGCLIENTENCODING=utf8
+# ------------------------------------------------------------------------------
+# 导出根目录
+EXPORT_ROOT=export/JSON
-# ETL配置
+# 日志根目录
+LOG_ROOT=export/LOG
+
+# 在线抓取 JSON 输出目录
+FETCH_ROOT=export/JSON
+
+# 本地入库数据源目录(INGEST_ONLY 模式使用)
+INGEST_SOURCE_DIR=export/test-json-doc
+
+# ------------------------------------------------------------------------------
+# 流水线配置
+# ------------------------------------------------------------------------------
+# 运行模式:FULL(抓取+入库)、FETCH_ONLY(仅抓取)、INGEST_ONLY(仅入库)
+PIPELINE_FLOW=FULL
+
+# JSON 美化输出(调试用,会增加文件大小)
+WRITE_PRETTY_JSON=false
+
+# ------------------------------------------------------------------------------
+# 时间窗口配置
+# ------------------------------------------------------------------------------
+# 冗余窗口(秒),向前多抓取的时间避免边界数据丢失
OVERLAP_SECONDS=120
+
+# 忙时窗口大小(分钟)
WINDOW_BUSY_MIN=30
+
+# 闲时窗口大小(分钟)
WINDOW_IDLE_MIN=180
+
+# 闲时窗口定义(HH:MM 格式)
IDLE_START=04:00
IDLE_END=16:00
+
+# 窗口切分单位(month/none),用于长时间回溯任务按月切分
+WINDOW_SPLIT_UNIT=month
+
+# 窗口前后补偿小时数,用于捕获边界数据
+WINDOW_COMPENSATION_HOURS=2
+
+# 允许空结果推进窗口
ALLOW_EMPTY_RESULT_ADVANCE=true
-# 清洗配置
-LOG_UNKNOWN_FIELDS=true
-HASH_ALGO=sha1
-STRICT_NUMERIC=true
-ROUND_MONEY_SCALE=2
+# ------------------------------------------------------------------------------
+# 数据完整性检查配置
+# ------------------------------------------------------------------------------
+# 检查模式:history(历史全量)、recent(最近增量)
+INTEGRITY_MODE=history
-# 测试/离线模式(真实库联调建议 ONLINE)
-TEST_MODE=ONLINE
-TEST_JSON_ARCHIVE_DIR=tests/source-data-doc
-TEST_JSON_TEMP_DIR=/tmp/etl_billiards_json_tmp
+# 历史检查起始日期(history 模式使用)
+INTEGRITY_HISTORY_START=2025-07-01
-# 测试数据库
-TEST_DB_DSN=postgresql://local-Python:Neo-local-1991125@100.64.0.4:5432/LLZQ-test
+# 历史检查结束日期(留空表示到当前)
+INTEGRITY_HISTORY_END=
-# ODS ؽűãã
-JSON_DOC_DIR=C:\dev\LLTQ\export\test-json-doc
-ODS_INCLUDE_FILES=
-ODS_DROP_SCHEMA_FIRST=true
+# 是否包含维度表校验
+INTEGRITY_INCLUDE_DIMENSIONS=true
+
+# 发现丢失数据时是否自动补全
+INTEGRITY_AUTO_BACKFILL=true
+
+# 自动执行完整性检查(ETL 完成后自动触发)
+INTEGRITY_AUTO_CHECK=false
+
+# 指定要校验的 ODS 任务代码(逗号分隔,留空表示全部)
+# INTEGRITY_ODS_TASK_CODES=ODS_PAYMENT,ODS_MEMBER
+
+# ------------------------------------------------------------------------------
+# 默认任务列表(逗号分隔,可被 CLI --tasks 参数覆盖)
+# ------------------------------------------------------------------------------
+# RUN_TASKS=ODS_PAYMENT,ODS_MEMBER,ODS_SETTLEMENT_RECORDS,DWD_LOAD_FROM_ODS
diff --git a/etl_billiards/ETL_Manager.exe - 快捷方式.lnk b/etl_billiards/ETL_Manager.exe - 快捷方式.lnk
new file mode 100644
index 0000000..6ec35ca
Binary files /dev/null and b/etl_billiards/ETL_Manager.exe - 快捷方式.lnk differ
diff --git a/etl_billiards/ETL_Manager.spec b/etl_billiards/ETL_Manager.spec
new file mode 100644
index 0000000..66892de
--- /dev/null
+++ b/etl_billiards/ETL_Manager.spec
@@ -0,0 +1,44 @@
+# -*- mode: python ; coding: utf-8 -*-
+
+
+a = Analysis(
+ ['C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\gui\\main.py'],
+ pathex=[],
+ binaries=[],
+ datas=[('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\gui\\resources', 'gui/resources'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\schema_dwd_doc.sql', 'database'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\schema_dws.sql', 'database'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\schema_etl_admin.sql', 'database'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\schema_ODS_doc.sql', 'database'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\seed_ods_tasks.sql', 'database'), ('C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\\database\\seed_scheduler_tasks.sql', 'database')],
+ hiddenimports=['PySide6.QtCore', 'PySide6.QtGui', 'PySide6.QtWidgets', 'psycopg2', 'psycopg2.extras', 'psycopg2.extensions', 'gui.models.task_model', 'gui.models.schedule_model', 'gui.utils.cli_builder', 'gui.utils.config_helper', 'gui.utils.app_settings', 'gui.workers.task_worker', 'gui.workers.db_worker', 'gui.widgets.settings_dialog'],
+ hookspath=[],
+ hooksconfig={},
+ runtime_hooks=[],
+ excludes=['matplotlib', 'numpy', 'pandas', 'scipy', 'PIL', 'cv2', 'tkinter'],
+ noarchive=False,
+ optimize=0,
+)
+pyz = PYZ(a.pure)
+
+exe = EXE(
+ pyz,
+ a.scripts,
+ [],
+ exclude_binaries=True,
+ name='ETL_Manager',
+ debug=False,
+ bootloader_ignore_signals=False,
+ strip=False,
+ upx=True,
+ console=False,
+ disable_windowed_traceback=False,
+ argv_emulation=False,
+ target_arch=None,
+ codesign_identity=None,
+ entitlements_file=None,
+)
+coll = COLLECT(
+ exe,
+ a.binaries,
+ a.datas,
+ strip=False,
+ upx=True,
+ upx_exclude=[],
+ name='ETL_Manager',
+)
diff --git a/etl_billiards/README.md b/etl_billiards/README.md
deleted file mode 100644
index c8acbeb..0000000
--- a/etl_billiards/README.md
+++ /dev/null
@@ -1,837 +0,0 @@
-# 台球场 ETL 系统(模块化版本)合并文档
-
-本文为原多份文档(如 `INDEX.md`、`QUICK_START.md`、`ARCHITECTURE.md`、`MIGRATION_GUIDE.md`、`PROJECT_STRUCTURE.md`、`README.md` 等)的合并版,只保留与**当前项目本身**相关的内容:项目说明、目录结构、架构设计、数据与控制流程、迁移与扩展指南等,不包含修改历史和重构过程描述。
-
----
-
-## 1. 项目概述
-
-台球场 ETL 系统是一个面向门店业务的专业 ETL 工程项目,用于从外部业务 API 拉取订单、支付、会员等数据,经过解析、校验、SCD2 处理、质量检查后写入 PostgreSQL 数据库,并支持增量同步和任务运行追踪。
-
-系统采用模块化、分层架构设计,核心特性包括:
-
-- 模块化目录结构(配置、数据库、API、模型、加载器、SCD2、质量检查、编排、任务、CLI、工具、测试等分层清晰)。
-- 完整的配置管理:默认值 + 环境变量 + CLI 参数多层覆盖。
-- 可复用的数据库访问层(连接管理、批量 Upsert 封装)。
-- 支持重试与分页的 API 客户端。
-- 类型安全的数据解析与校验模块。
-- SCD2 维度历史管理。
-- 数据质量检查(例如余额一致性检查)。
-- 任务编排层统一调度、游标管理与运行追踪。
-- 命令行入口统一管理任务执行,支持筛选任务、Dry-run 等模式。
-
----
-
-## 2. 快速开始
-
-### 2.1 环境准备
-
-- Python 版本:建议 3.10+
-- 数据库:PostgreSQL
-- 操作系统:Windows / Linux / macOS 均可
-
-```bash
-# 克隆/下载代码后进入项目目录
-cd etl_billiards/
-ls -la
-```
-
-你会看到下述目录结构的顶层部分(详细见第 4 章):
-
-- `config/` - 配置管理
-- `database/` - 数据库访问
-- `api/` - API 客户端
-- `tasks/` - ETL 任务实现
-- `cli/` - 命令行入口
-- `docs/` - 技术文档
-
-### 2.2 安装依赖
-
-```bash
-pip install -r requirements.txt
-```
-
-主要依赖示例(按实际 `requirements.txt` 为准):
-
-- `psycopg2-binary`:PostgreSQL 驱动
-- `requests`:HTTP 客户端
-- `python-dateutil`:时间处理
-- `tzdata`:时区数据
-
-### 2.3 配置环境变量
-
-复制并修改环境变量模板:
-
-```bash
-cp .env.example .env
-# 使用你习惯的编辑器修改 .env
-```
-
-`.env` 示例(最小配置):
-
-```bash
-# 数据库
-PG_DSN=postgresql://user:password@localhost:5432/....
-
-# API
-API_BASE=https://api.example.com
-API_TOKEN=your_token_here
-
-# 门店/应用
-STORE_ID=2790685415443269
-TIMEZONE=Asia/Taipei
-
-# 目录
-EXPORT_ROOT=/path/to/export
-LOG_ROOT=/path/to/logs
-```
-
-> 所有配置项的默认值见 `config/defaults.py`,最终生效配置由「默认值 + 环境变量 + CLI 参数」三层叠加。
-
-### 2.4 运行第一个任务
-
-通过 CLI 入口运行:
-
-```bash
-# 运行所有任务
-python -m cli.main
-
-# 仅运行订单任务
-python -m cli.main --tasks ORDERS
-
-# 运行订单 + 支付
-python -m cli.main --tasks ORDERS,PAYMENTS
-
-# Windows 使用脚本
-run_etl.bat --tasks ORDERS
-
-# Linux / macOS 使用脚本
-./run_etl.sh --tasks ORDERS
-```
-
-### 2.5 查看结果
-
-- 日志目录:使用 `LOG_ROOT` 指定,例如
-
- ```bash
- ls -la C:\dev\LLTQ\export\LOG/
- ```
-
-- 导出目录:使用 `EXPORT_ROOT` 指定,例如
-
- ```bash
- ls -la C:\dev\LLTQ\export\JSON/
- ```
-
----
-
-## 3. 常用命令与开发工具
-
-### 3.1 CLI 常用命令
-
-```bash
-# 运行所有任务
-python -m cli.main
-
-# 运行指定任务
-python -m cli.main --tasks ORDERS,PAYMENTS,MEMBERS
-
-# 使用自定义数据库
-python -m cli.main --pg-dsn "postgresql://user:password@host:5432/db"
-
-# 使用自定义 API 端点
-python -m cli.main --api-base "https://api.example.com" --api-token "..."
-
-# 试运行(不写入数据库)
-python -m cli.main --dry-run --tasks ORDERS
-```
-
-### 3.2 IDE / 代码质量工具(示例:VSCode)
-
-`.vscode/settings.json` 示例:
-
-```json
-{
- "python.linting.enabled": true,
- "python.linting.pylintEnabled": true,
- "python.formatting.provider": "black",
- "python.testing.pytestEnabled": true
-}
-```
-
-代码格式化与检查:
-
-```bash
-pip install black isort pylint
-
-black .
-isort .
-pylint etl_billiards/
-```
-
-### 3.3 测试
-
-```bash
-# 安装测试依赖(按需)
-pip install pytest pytest-cov
-
-# 运行全部测试
-pytest
-
-# 仅运行单元测试
-pytest tests/unit/
-
-# 生成覆盖率报告
-pytest --cov=. --cov-report=html
-```
-
-测试示例(按实际项目为准):
-
-- `tests/unit/test_config.py` – 配置管理单元测试
-- `tests/unit/test_parsers.py` – 解析器单元测试
-- `tests/integration/test_database.py` – 数据库集成测试
-
-#### 3.3.1 测试模式(ONLINE / OFFLINE)
-
-- `TEST_MODE=ONLINE`(默认)时,测试会模拟实时 API,完整执行 E/T/L。
-- `TEST_MODE=OFFLINE` 时,测试改为从 `TEST_JSON_ARCHIVE_DIR` 指定的归档 JSON 中读取数据,仅做 Transform + Load,适合验证本地归档数据是否仍可回放。
-- `TEST_JSON_ARCHIVE_DIR`:离线 JSON 归档目录(示例:`tests/source-data-doc` 或 CI 产出的快照)。
-- `TEST_JSON_TEMP_DIR`:测试生成的临时 JSON 输出目录,便于隔离每次运行的数据。
-- `TEST_DB_DSN`:可选,若设置则单元测试会连接到此 PostgreSQL DSN,实打实执行写库;留空时测试使用内存伪库,避免依赖数据库。
-
-示例命令:
-
-```bash
-# 在线模式覆盖所有任务
-TEST_MODE=ONLINE pytest tests/unit/test_etl_tasks_online.py
-
-# 离线模式使用归档 JSON 覆盖所有任务
-TEST_MODE=OFFLINE TEST_JSON_ARCHIVE_DIR=tests/source-data-doc pytest tests/unit/test_etl_tasks_offline.py
-
-# 使用脚本按需组合参数(示例:在线 + 仅订单用例)
-python scripts/run_tests.py --suite online --mode ONLINE --keyword ORDERS
-
-# 使用脚本连接真实测试库并回放离线模式
-python scripts/run_tests.py --suite offline --mode OFFLINE --db-dsn postgresql://user:pwd@localhost:5432/testdb
-
-# 使用“指令仓库”中的预置命令
-python scripts/run_tests.py --preset offline_realdb
-python scripts/run_tests.py --list-presets # 查看或自定义 scripts/test_presets.py
-```
-
-#### 3.3.2 脚本化测试组合(`run_tests.py` / `test_presets.py`)
-
-- `scripts/run_tests.py` 是 pytest 的统一入口:自动把项目根目录加入 `sys.path`,并提供 `--suite online/offline/integration`、`--tests`(自定义路径)、`--mode`、`--db-dsn`、`--json-archive`、`--json-temp`、`--keyword/-k`、`--pytest-args`、`--env KEY=VALUE` 等参数,可以像搭积木一样自由组合;
-- `--preset foo` 会读取 `scripts/test_presets.py` 内 `PRESETS["foo"]` 的配置,并叠加到当前命令;`--list-presets` 与 `--dry-run` 可用来审阅或仅打印命令;
-- 直接执行 `python scripts/test_presets.py` 可依次运行 `AUTO_RUN_PRESETS` 中列出的预置;传入 `--preset x --dry-run` 则只打印对应命令。
-
-`test_presets.py` 充当“指令仓库”。每个预置都是一个字典,常用字段解释如下:
-
-| 字段 | 作用 |
-| ---------------------------- | ------------------------------------------------------------------ |
-| `suite` | 复用 `run_tests.py` 内置套件(online/offline/integration,可多选) |
-| `tests` | 追加任意 pytest 路径,例如 `tests/unit/test_config.py` |
-| `mode` | 覆盖 `TEST_MODE`(ONLINE / OFFLINE) |
-| `db_dsn` | 覆盖 `TEST_DB_DSN`,用于连入真实测试库 |
-| `json_archive` / `json_temp` | 配置离线 JSON 归档与临时目录 |
-| `keyword` | 映射到 `pytest -k`,用于关键字过滤 |
-| `pytest_args` | 附加 pytest 参数,例 `-vv --maxfail=1` |
-| `env` | 额外环境变量列表,如 `["STORE_ID=123"]` |
-| `preset_meta` | 说明性文字,便于描述场景 |
-
-示例:`offline_realdb` 预置会设置 `TEST_MODE=OFFLINE`、指定 `tests/source-data-doc` 为归档目录,并通过 `db_dsn` 连到测试库。执行 `python scripts/run_tests.py --preset offline_realdb` 或 `python scripts/test_presets.py --preset offline_realdb` 即可复用该组合,保证本地、CI 与生产回放脚本一致。
-
-#### 3.3.3 数据库连通性快速检查
-
-`python scripts/test_db_connection.py` 提供最轻量的 PostgreSQL 连通性检测:默认使用 `TEST_DB_DSN`(也可传 `--dsn`),尝试连接并执行 `SELECT 1 AS ok`(可通过 `--query` 自定义)。典型用途:
-
-```bash
-# 读取 .env/环境变量中的 TEST_DB_DSN
-python scripts/test_db_connection.py
-
-# 临时指定 DSN,并检查任务配置表
-python scripts/test_db_connection.py --dsn postgresql://user:pwd@host:5432/.... --query "SELECT count(*) FROM etl_admin.etl_task"
-```
-
-脚本返回 0 代表连接与查询成功;若返回非 0,可结合第 8 章“常见问题排查”的数据库章节(网络、防火墙、账号权限等)先定位问题,再运行完整 ETL。
-
----
-
-## 4. 项目结构与文件说明
-
-### 4.1 总体目录结构(树状图)
-
-```text
-etl_billiards/
-│
-├── README.md # 项目总览和使用说明
-├── MIGRATION_GUIDE.md # 从旧版本迁移指南
-├── requirements.txt # Python 依赖列表
-├── setup.py # 项目安装配置
-├── .env.example # 环境变量配置模板
-├── .gitignore # Git 忽略文件配置
-├── run_etl.sh # Linux/Mac 运行脚本
-├── run_etl.bat # Windows 运行脚本
-│
-├── config/ # 配置管理模块
-│ ├── __init__.py
-│ ├── defaults.py # 默认配置值定义
-│ ├── env_parser.py # 环境变量解析器
-│ └── settings.py # 配置管理主类
-│
-├── database/ # 数据库访问层
-│ ├── __init__.py
-│ ├── connection.py # 数据库连接管理
-│ └── operations.py # 批量操作封装
-│
-├── api/ # HTTP API 客户端
-│ ├── __init__.py
-│ └── client.py # API 客户端(重试 + 分页)
-│
-├── models/ # 数据模型层
-│ ├── __init__.py
-│ ├── parsers.py # 类型解析器
-│ └── validators.py # 数据验证器
-│
-├── loaders/ # 数据加载器层
-│ ├── __init__.py
-│ ├── base_loader.py # 加载器基类
-│ ├── dimensions/ # 维度表加载器
-│ │ ├── __init__.py
-│ │ └── member.py # 会员维度加载器
-│ └── facts/ # 事实表加载器
-│ ├── __init__.py
-│ ├── order.py # 订单事实表加载器
-│ └── payment.py # 支付记录加载器
-│
-├── scd/ # SCD2 处理层
-│ ├── __init__.py
-│ └── scd2_handler.py # SCD2 历史记录处理器
-│
-├── quality/ # 数据质量检查层
-│ ├── __init__.py
-│ ├── base_checker.py # 质量检查器基类
-│ └── balance_checker.py # 余额一致性检查器
-│
-├── orchestration/ # ETL 编排层
-│ ├── __init__.py
-│ ├── scheduler.py # ETL 调度器
-│ ├── task_registry.py # 任务注册表(工厂模式)
-│ ├── cursor_manager.py # 游标管理器
-│ └── run_tracker.py # 运行记录追踪器
-│
-├── tasks/ # ETL 任务层
-│ ├── __init__.py
-│ ├── base_task.py # 任务基类(模板方法)
-│ ├── orders_task.py # 订单 ETL 任务
-│ ├── payments_task.py # 支付 ETL 任务
-│ └── members_task.py # 会员 ETL 任务
-│
-├── cli/ # 命令行接口层
-│ ├── __init__.py
-│ └── main.py # CLI 主入口
-│
-├── utils/ # 工具函数
-│ ├── __init__.py
-│ └── helpers.py # 通用工具函数
-│
-├── tests/ # 测试代码
-│ ├── __init__.py
-│ ├── unit/ # 单元测试
-│ │ ├── __init__.py
-│ │ ├── test_config.py
-│ │ └── test_parsers.py
-│ ├── testdata_json/ # 清洗入库用的测试Json文件
-│ │ └── XX.json
-│ └── integration/ # 集成测试
-│ ├── __init__.py
-│ └── test_database.py
-│
-└── docs/ # 文档
- └── ARCHITECTURE.md # 架构设计文档
-```
-
-### 4.2 各模块职责概览
-
-- **config/**
- - 统一配置入口,支持默认值、环境变量、命令行参数三层覆盖。
-- **database/**
- - 封装 PostgreSQL 连接与批量操作(插入、更新、Upsert 等)。
-- **api/**
- - 对上游业务 API 的 HTTP 调用进行统一封装,支持重试、分页与超时控制。
-- **models/**
- - 提供类型解析器(时间戳、金额、整数等)与业务级数据校验器。
-- **loaders/**
- - 提供事实表与维度表的加载逻辑(包含批量 Upsert、统计写入结果等)。
-- **scd/**
- - 维度型数据的 SCD2 历史管理(有效期、版本标记等)。
-- **quality/**
- - 质量检查策略,例如余额一致性、记录数量对齐等。
-- **orchestration/**
- - 任务调度、任务注册、游标管理(增量窗口)、运行记录追踪。
-- **tasks/**
- - 具体业务任务(订单、支付、会员等),封装了从“取数 → 处理 → 写库 → 记录结果”的完整流程。
-- **cli/**
- - 命令行入口,解析参数并启动调度流程。
-- **utils/**
- - 杂项工具函数。
-- **tests/**
- - 单元测试与集成测试代码。
-
----
-
-## 5. 架构设计与流程说明
-
-### 5.1 分层架构图
-
-```text
-┌─────────────────────────────────────┐
-│ CLI 命令行接口 │ <- cli/main.py
-└─────────────┬───────────────────────┘
- │
-┌─────────────▼───────────────────────┐
-│ Orchestration 编排层 │ <- orchestration/
-│ (Scheduler, TaskRegistry, ...) │
-└─────────────┬───────────────────────┘
- │
-┌─────────────▼───────────────────────┐
-│ Tasks 任务层 │ <- tasks/
-│ (OrdersTask, PaymentsTask, ...) │
-└───┬─────────┬─────────┬─────────────┘
- │ │ │
- ▼ ▼ ▼
-┌────────┐ ┌─────┐ ┌──────────┐
-│Loaders │ │ SCD │ │ Quality │ <- loaders/, scd/, quality/
-└────────┘ └─────┘ └──────────┘
- │
- ┌───────▼────────┐
- │ Models 模型 │ <- models/
- └───────┬────────┘
- │
- ┌───────▼────────┐
- │ API 客户端 │ <- api/
- └───────┬────────┘
- │
- ┌───────▼────────┐
- │ Database 访问 │ <- database/
- └───────┬────────┘
- │
- ┌───────▼────────┐
- │ Config 配置 │ <- config/
- └────────────────┘
-```
-
-### 5.2 各层职责(当前设计)
-
-- **CLI 层 (`cli/`)**
-
- - 解析命令行参数(指定任务列表、Dry-run、覆盖配置项等)。
- - 初始化配置与日志后交由编排层执行。
-
-- **编排层 (`orchestration/`)**
-
- - `scheduler.py`:根据配置与 CLI 参数选择需要执行的任务,控制执行顺序和并行策略。
- - `task_registry.py`:提供任务注册表,按任务代码创建任务实例(工厂模式)。
- - `cursor_manager.py`:管理增量游标(时间窗口 / ID 游标)。
- - `run_tracker.py`:记录每次任务运行的状态、统计信息和错误信息。
-
-- **任务层 (`tasks/`)**
-
- - `base_task.py`:定义任务执行模板流程(模板方法模式),包括获取窗口、调用上游、解析 / 校验、写库、更新游标等。
- - `orders_task.py` / `payments_task.py` / `members_task.py`:实现具体任务逻辑(订单、支付、会员)。
-
-- **加载器 / SCD / 质量层**
-
- - `loaders/`:根据目标表封装 Upsert / Insert / Update 逻辑。
- - `scd/scd2_handler.py`:为维度表提供 SCD2 历史管理能力。
- - `quality/`:执行数据质量检查,如余额对账。
-
-- **模型层 (`models/`)**
-
- - `parsers.py`:负责数据类型转换(字符串 → 时间戳、Decimal、int 等)。
- - `validators.py`:执行字段级和记录级的数据校验。
-
-- **API 层 (`api/client.py`)**
-
- - 封装 HTTP 调用,处理重试、超时及分页。
-
-- **数据库层 (`database/`)**
-
- - 管理数据库连接及上下文。
- - 提供批量插入 / 更新 / Upsert 操作接口。
-
-- **配置层 (`config/`)**
- - 定义配置项默认值。
- - 解析环境变量并进行类型转换。
- - 对外提供统一配置对象。
-
-### 5.3 设计模式(当前使用)
-
-- 工厂模式:任务注册 / 创建(`TaskRegistry`)。
-- 模板方法模式:任务执行流程(`BaseTask`)。
-- 策略模式:不同 Loader / Checker 实现不同策略。
-- 依赖注入:通过构造函数向任务传入 `db`、`api`、`config` 等依赖。
-
-### 5.4 数据与控制流程
-
-整体流程:
-
-1. CLI 解析参数并加载配置。
-2. Scheduler 构建数据库连接、API 客户端等依赖。
-3. Scheduler 遍历任务配置,从 `TaskRegistry` 获取任务类并实例化。
-4. 每个任务按统一模板执行:
- - 读取游标 / 时间窗口。
- - 调用 API 拉取数据(可分页)。
- - 解析、验证数据。
- - 通过 Loader 写入数据库(事实表 / 维度表 / SCD2)。
- - 执行质量检查。
- - 更新游标与运行记录。
-5. 所有任务执行完成后,释放连接并退出进程。
-
-### 5.5 错误处理策略
-
-- 单个任务失败不影响其他任务执行。
-- 数据库操作异常自动回滚当前事务。
-- API 请求失败时按配置进行重试,超过重试次数记录错误并终止该任务。
-- 所有错误被记录到日志和运行追踪表,便于事后排查。
-
-### 5.6 ODS + DWD 双阶段策略(新增)
-
-为了支撑回溯/重放与后续 DWD 宽表构建,项目新增了 `billiards_ods` Schema 以及一组专门的 ODS 任务/Loader:
-
-- **ODS 表**:`billiards_ods.ods_order_settle`、`ods_table_use_detail`、`ods_assistant_ledger`、`ods_assistant_abolish`、`ods_goods_ledger`、`ods_payment`、`ods_refund`、`ods_coupon_verify`、`ods_member`、`ods_member_card`、`ods_package_coupon`、`ods_inventory_stock`、`ods_inventory_change`。每条记录都会保存 `store_id + 源主键 + payload JSON + fetched_at + source_endpoint` 等信息。
-- **通用 Loader**:`loaders/ods/generic.py::GenericODSLoader` 统一封装了 `INSERT ... ON CONFLICT ...` 与批量写入逻辑,调用方只需提供列名与主键列即可。
-- **ODS 任务**:`tasks/ods_tasks.py` 内通过 `OdsTaskSpec` 定义了一组任务(`ODS_ORDER_SETTLE`、`ODS_PAYMENT`、`ODS_ASSISTANT_LEDGER` 等),并在 `TaskRegistry` 中自动注册,可直接通过 `python -m cli.main --tasks ODS_ORDER_SETTLE,ODS_PAYMENT` 执行。
-- **双阶段链路**:
- 1. 阶段 1(ODS):调用 API/离线归档 JSON,将原始记录写入 ODS 表,保留分页、抓取时间、来源文件等元数据。
- 2. 阶段 2(DWD/DIM):后续订单、支付、券等事实任务将改为从 ODS 读取 payload,经过解析/校验后写入 `billiards.fact_*`、`dim_*` 表,避免重复拉取上游接口。
-
-> 新增的单元测试 `tests/unit/test_ods_tasks.py` 覆盖了 `ODS_ORDER_SETTLE`、`ODS_PAYMENT` 的入库路径,可作为扩展其他 ODS 任务的模板。
-
----
-
-## 6. 迁移指南(从旧脚本到当前项目)
-
-本节用于说明如何从旧的单文件脚本(如 `task_merged.py`)迁移到当前模块化项目,属于当前项目的使用说明,不涉及历史对比细节。
-
-### 6.1 核心功能映射示意
-
-| 旧版本函数 / 类 | 新版本位置 | 说明 |
-| --------------------- | ----------------------------------------------------- | ---------- |
-| `DEFAULTS` 字典 | `config/defaults.py` | 配置默认值 |
-| `build_config()` | `config/settings.py::AppConfig.load()` | 配置加载 |
-| `Pg` 类 | `database/connection.py::DatabaseConnection` | 数据库连接 |
-| `http_get_json()` | `api/client.py::APIClient.get()` | API 请求 |
-| `paged_get()` | `api/client.py::APIClient.get_paginated()` | 分页请求 |
-| `parse_ts()` | `models/parsers.py::TypeParser.parse_timestamp()` | 时间解析 |
-| `upsert_fact_order()` | `loaders/facts/order.py::OrderLoader.upsert_orders()` | 订单加载 |
-| `scd2_upsert()` | `scd/scd2_handler.py::SCD2Handler.upsert()` | SCD2 处理 |
-| `run_task_orders()` | `tasks/orders_task.py::OrdersTask.execute()` | 订单任务 |
-| `main()` | `cli/main.py::main()` | 主入口 |
-
-### 6.2 典型迁移步骤
-
-1. **配置迁移**
-
- - 原来在 `DEFAULTS` 或脚本内硬编码的配置,迁移到 `.env` 与 `config/defaults.py`。
- - 使用 `AppConfig.load()` 统一获取配置。
-
-2. **并行运行验证**
-
- ```bash
- # 旧脚本
- python task_merged.py --tasks ORDERS
-
- # 新项目
- python -m cli.main --tasks ORDERS
- ```
-
- 对比新旧版本导出的数据表和日志,确认一致性。
-
-3. **自定义逻辑迁移**
-
- - 原脚本中的自定义清洗逻辑 → 放入相应 `loaders/` 或任务类中。
- - 自定义任务 → 在 `tasks/` 中实现并在 `task_registry` 中注册。
- - 自定义 API 调用 → 扩展 `api/client.py` 或单独封装服务类。
-
-4. **逐步切换**
- - 先在测试环境并行运行。
- - 再逐步切换生产任务到新版本。
-
----
-
-## 7. 开发与扩展指南(当前项目)
-
-### 7.1 添加新任务
-
-1. 在 `tasks/` 目录创建任务类:
-
-```python
-from .base_task import BaseTask
-
-class MyTask(BaseTask):
- def get_task_code(self) -> str:
- return "MY_TASK"
-
- def execute(self) -> dict:
- # 1. 获取时间窗口
- window_start, window_end, _ = self._get_time_window()
-
- # 2. 调用 API 获取数据
- records, _ = self.api.get_paginated(...)
-
- # 3. 解析 / 校验
- parsed = [self._parse(r) for r in records]
-
- # 4. 加载数据
- loader = MyLoader(self.db)
- inserted, updated, _ = loader.upsert(parsed)
-
- # 5. 提交并返回结果
- self.db.commit()
- return self._build_result("SUCCESS", {
- "inserted": inserted,
- "updated": updated,
- })
-```
-
-2. 在 `orchestration/task_registry.py` 中注册:
-
-```python
-from tasks.my_task import MyTask
-
-default_registry.register("MY_TASK", MyTask)
-```
-
-3. 在任务配置表中启用(示例):
-
-```sql
-INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
-VALUES ('MY_TASK', 123456, TRUE);
-```
-
-### 7.2 添加新加载器
-
-```python
-from loaders.base_loader import BaseLoader
-
-class MyLoader(BaseLoader):
- def upsert(self, records: list) -> tuple:
- sql = "INSERT INTO table_name (...) VALUES (...) ON CONFLICT (...) DO UPDATE SET ... RETURNING (xmax = 0) AS inserted"
- inserted, updated = self.db.batch_upsert_with_returning(
- sql, records, page_size=self._batch_size()
- )
- return (inserted, updated, 0)
-```
-
-### 7.3 添加新质量检查器
-
-1. 在 `quality/` 中实现检查器,继承 `base_checker.py`。
-2. 在任务或调度流程中调用该检查器,在写库后进行验证。
-
-### 7.4 类型解析与校验扩展
-
-- 在 `models/parsers.py` 中添加新类型解析方法。
-- 在 `models/validators.py` 中添加新规则(如枚举校验、跨字段校验等)。
-
----
-
-## 8. 常见问题排查
-
-### 8.1 数据库连接失败
-
-```text
-错误: could not connect to server
-```
-
-排查要点:
-
-- 检查 `PG_DSN` 或相关数据库配置是否正确。
-- 确认数据库服务是否启动、网络是否可达。
-
-### 8.2 API 请求超时
-
-```text
-错误: requests.exceptions.Timeout
-```
-
-排查要点:
-
-- 检查 `API_BASE` 地址与网络连通性。
-- 适当提高超时与重试次数(在配置中调整)。
-
-### 8.3 模块导入错误
-
-```text
-错误: ModuleNotFoundError
-```
-
-排查要点:
-
-- 确认在项目根目录下运行(包含 `etl_billiards/` 包)。
-- 或通过 `pip install -e .` 以可编辑模式安装项目。
-
-### 8.4 权限相关问题
-
-```text
-错误: Permission denied
-```
-
-排查要点:
-
-- 脚本无执行权限:`chmod +x run_etl.sh`。
-- Windows 需要以管理员身份运行,或修改日志 / 导出目录权限。
-
----
-
-## 9. 使用前检查清单
-
-在正式运行前建议确认:
-
-- [ ] 已安装 Python 3.10+。
-- [ ] 已执行 `pip install -r requirements.txt`。
-- [ ] `.env` 已配置正确(数据库、API、门店 ID、路径等)。
-- [ ] PostgreSQL 数据库可连接。
-- [ ] API 服务可访问且凭证有效。
-- [ ] `LOG_ROOT`、`EXPORT_ROOT` 目录存在且拥有写权限。
-
----
-
-## 10. 参考说明
-
-- 本文已合并原有的快速开始、项目结构、架构说明、迁移指南等内容,可作为当前项目的统一说明文档。
-- 如需在此基础上拆分多份文档,可按章节拆出,例如「快速开始」「架构设计」「迁移指南」「开发扩展」等。
-
-## 11. 运行/调试模式说明
-
-- 生产环境仅保留“任务模式”:通过调度/CLI 执行注册的任务(ETL/ODS),不使用调试脚本。
-- 开发/调试可使用的辅助脚本(上线前可删除或禁用):
- - `python -m etl_billiards.scripts.rebuild_ods_from_json`:从本地 JSON 目录重建 `billiards_ods`,用于离线初始化/验证。环境变量:`PG_DSN`(必填)、`JSON_DOC_DIR`(可选,默认 `C:\dev\LLTQ\export\test-json-doc`)、`INCLUDE_FILES`(逗号分隔文件名)、`DROP_SCHEMA_FIRST`(默认 true)。
-- 如需在生产环境保留脚本,请在运维手册中明确用途和禁用条件,避免误用。
-
-## 12. ODS 任务上线指引
-
-- 任务注册:`etl_billiards/database/seed_ods_tasks.sql` 列出了当前启用的 ODS 任务。将其中的 `store_id` 替换为实际门店后执行:
- ```
- psql "$PG_DSN" -f etl_billiards/database/seed_ods_tasks.sql
- ```
- `ON CONFLICT` 会保持 enabled=true,避免重复。
-- 调度:确认 `etl_admin.etl_task` 中已启用所需的 ODS 任务(任务代码见 seed 脚本),调度器或 CLI `--tasks` 即可调用。
-- 离线回灌:开发环境可用 `rebuild_ods_from_json` 以样例 JSON 初始化 ODS,生产慎用;默认按 `(source_file, record_index)` 去重。
-- 测试:`pytest etl_billiards/tests/unit/test_ods_tasks.py` 覆盖核心 ODS 任务;测试时可设置 `ETL_SKIP_DOTENV=1` 跳过本地 .env 读取。
-
-## 13. ODS 表映射总览
-
-| ODS 表名 | 接口 Path | 数据列表路径 |
-| ------------------------------------ | ---------------------------------------------------- | ----------------------------- |
-| `assistant_accounts_master` | `/PersonnelManagement/SearchAssistantInfo` | data.assistantInfos |
-| `assistant_service_records` | `/AssistantPerformance/GetOrderAssistantDetails` | data.orderAssistantDetails |
-| `assistant_cancellation_records` | `/AssistantPerformance/GetAbolitionAssistant` | data.abolitionAssistants |
-| `goods_stock_movements` | `/GoodsStockManage/QueryGoodsOutboundReceipt` | data.queryDeliveryRecordsList |
-| `goods_stock_summary` | `/TenantGoods/GetGoodsStockReport` | data |
-| `group_buy_packages` | `/PackageCoupon/QueryPackageCouponList` | data.packageCouponList |
-| `group_buy_redemption_records` | `/Site/GetSiteTableUseDetails` | data.siteTableUseDetailsList |
-| `member_profiles` | `/MemberProfile/GetTenantMemberList` | data.tenantMemberInfos |
-| `member_balance_changes` | `/MemberProfile/GetMemberCardBalanceChange` | data.tenantMemberCardLogs |
-| `member_stored_value_cards` | `/MemberProfile/GetTenantMemberCardList` | data.tenantMemberCards |
-| `payment_transactions` | `/PayLog/GetPayLogListPage` | data |
-| `platform_coupon_redemption_records` | `/Promotion/GetOfflineCouponConsumePageList` | data |
-| `recharge_settlements` | `/Site/GetRechargeSettleList` | data.settleList |
-| `refund_transactions` | `/Order/GetRefundPayLogList` | data |
-| `settlement_records` | `/Site/GetAllOrderSettleList` | data.settleList |
-| `settlement_ticket_details` | `/Order/GetOrderSettleTicketNew` | (整包原始 JSON) |
-| `site_tables_master` | `/Table/GetSiteTables` | data.siteTables |
-| `stock_goods_category_tree` | `/TenantGoodsCategory/QueryPrimarySecondaryCategory` | data.goodsCategoryList |
-| `store_goods_master` | `/TenantGoods/GetGoodsInventoryList` | data.orderGoodsList |
-| `store_goods_sales_records` | `/TenantGoods/GetGoodsSalesList` | data.orderGoodsLedgers |
-| `table_fee_discount_records` | `/Site/GetTaiFeeAdjustList` | data.taiFeeAdjustInfos |
-| `table_fee_transactions` | `/Site/GetSiteTableOrderDetails` | data.siteTableUseDetailsList |
-| `tenant_goods_master` | `/TenantGoods/QueryTenantGoods` | data.tenantGoodsList |
-
-## 14. ODS 相关环境变量/默认值
-
-- `.env` / 环境变量:
- - `JSON_DOC_DIR`:ODS 样例 JSON 目录(开发/回灌用)
- - `ODS_INCLUDE_FILES`:限定导入的文件名(逗号分隔,不含 .json)
- - `ODS_DROP_SCHEMA_FIRST`:true/false,是否重建 schema
- - `ETL_SKIP_DOTENV`:测试/CI 时设为 1 跳过本地 .env 读取
-- `config/defaults.py` 中 `ods` 默认值:
- - `json_doc_dir`: `C:\dev\LLTQ\export\test-json-doc`
- - `include_files`: `""`
- - `drop_schema_first`: `True`
-
----
-
-## 15. DWD 维度 “业务事件”
-
-1. 粒度唯一、原子
-
-- 一张 DWD 表只能有一种业务粒度,比如:
- - 一条记录 = 一次结账;
- - 一条记录 = 一段台费流水;
- - 一条记录 = 一次助教服务;
- - 一条记录 = 一次会员余额变动。
-- 表里面不能又混“订单头”又混“订单行”,不能一部分是“汇总”,一部分是“明细”。
-- 一旦粒度确定,所有字段都要跟这个粒度匹配:
- - 比如“结账头表”就不要塞每一行商品明细;
- - 商品明细就不要塞整单级别的总金额。
- - 这是 DWD 层最重要的一条。
-
-2. 以业务过程建模,不以 JSON 列表建模
-
-- 先画清楚你真实的业务链路:
- - 开台 / 换台 / 关台 → 台费流水
- - 助教上桌 → 助教服务流水 / 废除事件
- - 点单 → 商品销售流水
- - 充值 / 消费 → 余额变更 / 充值单
- - 结账 → 结账头表 + 支付流水 / 退款流水
- - 团购 / 平台券 → 核销流水
-
-3. 主键明确、外键统一
-
-- 每张 DWD 表必须有业务主键(哪怕是接口给的 id),不要依赖数据库自增。
-- 所有“同一概念”的字段必须统一命名、统一含义:
- - 门店:统一叫 site_id,都对应 siteProfile.id;
- - 会员:统一叫 member_id 对应 member_profiles.id,system_member_id 单独一列;
- - 台桌:统一 table_id 对应 site_tables_master.id;
- - 结账:统一 order_settle_id;
- - 订单:统一 order_trade_no 等。
-- 否则后面 DWS、AI 要把表拼起来会非常痛苦。
-
-4. 保留明细,不做过度汇总
-
-- DWD 层的事实表原则上只做“明细级”的数据:
- - 不要在 DWD 就把“日汇总、周汇总、月汇总”算出来,那是 DWS 的事;
- - 也不要把多个事件折成一行(例如一张表同时放日汇总+单笔流水)。
-- 需要聚合时,再在 DWS 做主题宽表:
- - dws_member_day_profile、dws_site_day_summary 等。
-- DWD 只负责细颗粒度的真相。
-
-5. 统一清洗、标准化,但保持可追溯
-
-- 在 DWD 层一定要做的清洗:
- - 类型转换:字符串时间 → 时间类型,金额统一为 decimal,布尔统一为 0/1;
- - 单位统一:秒 / 分钟、元 / 分都统一;
- - 枚举标准化:状态码、类型码在 DWD 里就定死含义,必要时建枚举维表。
-- 同时要保证:
- - 每条 DWD 记录都能追溯回 ODS:
-- 保留源系统主键;
- - 保留原始时间 / 原始金额字段(不要覆盖掉)。
-
-6. 扁平化、去嵌套
-
-- JSON 里常见结构是:分页壳 + 头 + 明细数组 + 各种嵌套对象(siteProfile、tableProfile、goodsLedgers…)。
-- DWD 的原则是:
- - 去掉分页壳;
- - 把“数组”拆成子表(头表 / 行表);
- - 把重复出现的 profile 抽出去做维度表(门店、台、商品、会员……)。
-- 目标是:DWD 表都是二维表结构,不存复杂嵌套 JSON。
-
-7. 模型长期稳定,可扩展
-
-- DWD 的表结构要尽可能稳定,新增需求尽量通过:
- - 加字段;
- - 新建事实表 / 维度表;
- - 在 DWS 做派生指标;
- - 而不是频繁重构已有 DWD 表结构。
-- 这点跟你后面要喂给 LLM 也很相关:AI 配的 prompt、schema 理解都要尽量少改。
diff --git a/etl_billiards/api/client.py b/etl_billiards/api/client.py
index 1ee807e..0959c01 100644
--- a/etl_billiards/api/client.py
+++ b/etl_billiards/api/client.py
@@ -8,6 +8,8 @@ import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
+from api.endpoint_routing import plan_calls
+
DEFAULT_BROWSER_HEADERS = {
"Accept": "application/json, text/plain, */*",
"Content-Type": "application/json",
@@ -142,7 +144,7 @@ class APIClient:
raise ValueError(f"API 返回错误 code={code} msg={msg}")
# ------------------------------------------------------------------ 分页
- def iter_paginated(
+ def _iter_paginated_single(
self,
endpoint: str,
params: dict | None,
@@ -155,8 +157,7 @@ class APIClient:
page_end: int | None = None,
) -> Iterable[tuple[int, list, dict, dict]]:
"""
- 分页迭代器:逐页拉取数据并产出 (page_no, records, request_params, raw_response)。
- page_size=None 时不附带分页参数,仅拉取一次。
+ 单一 endpoint 的分页迭代器(不包含 recent/former 路由逻辑)。
"""
base_params = dict(params or {})
page = page_start
@@ -183,6 +184,42 @@ class APIClient:
page += 1
+ def iter_paginated(
+ self,
+ endpoint: str,
+ params: dict | None,
+ page_size: int | None = 200,
+ page_field: str = "page",
+ size_field: str = "limit",
+ data_path: tuple = ("data",),
+ list_key: str | Sequence[str] | None = None,
+ page_start: int = 1,
+ page_end: int | None = None,
+ ) -> Iterable[tuple[int, list, dict, dict]]:
+ """
+ 分页迭代器:逐页拉取数据并产出 (page_no, records, request_params, raw_response)。
+ page_size=None 时不附带分页参数,仅拉取一次。
+ """
+ # recent/former 路由:当 params 带时间范围字段时,按“3个月自然月”边界决定走哪个 endpoint,
+ # 跨越边界则拆分为两段请求并顺序产出,确保调用方使用 page_no 命名文件时不会被覆盖。
+ call_plan = plan_calls(endpoint, params)
+ global_page = 1
+
+ for call in call_plan:
+ for _, records, request_params, payload in self._iter_paginated_single(
+ endpoint=call.endpoint,
+ params=call.params,
+ page_size=page_size,
+ page_field=page_field,
+ size_field=size_field,
+ data_path=data_path,
+ list_key=list_key,
+ page_start=page_start,
+ page_end=page_end,
+ ):
+ yield global_page, records, request_params, payload
+ global_page += 1
+
def get_paginated(
self,
endpoint: str,
diff --git a/etl_billiards/api/endpoint_routing.py b/etl_billiards/api/endpoint_routing.py
new file mode 100644
index 0000000..8ddc4e0
--- /dev/null
+++ b/etl_billiards/api/endpoint_routing.py
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+"""
+“近期记录 / 历史记录(Former)”接口路由规则。
+
+需求:
+- 当请求参数包含可定义时间范围的字段时,根据当前时间(北京时间/上海时区)判断:
+ - 3个月(自然月)之前 -> 使用“历史记录”接口
+ - 3个月以内 -> 使用“近期记录”接口
+ - 若时间范围跨越边界 -> 拆分为两段分别请求并合并(由上层分页迭代器顺序产出)
+"""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from datetime import datetime
+from typing import Optional
+
+from dateutil import parser as dtparser
+from dateutil.relativedelta import relativedelta
+from zoneinfo import ZoneInfo
+
+
+ROUTING_TZ = ZoneInfo("Asia/Shanghai")
+RECENT_MONTHS = 3
+
+
+# 按 `fetch-test/recent_vs_former_report.md` 更新(“无”表示没有历史接口;相同 path 表示同一个接口可查历史)
+RECENT_TO_FORMER_OVERRIDES: dict[str, str | None] = {
+ "/AssistantPerformance/GetAbolitionAssistant": None,
+ "/Site/GetSiteTableUseDetails": "/Site/GetSiteTableUseDetails",
+ "/GoodsStockManage/QueryGoodsOutboundReceipt": "/GoodsStockManage/QueryFormerGoodsOutboundReceipt",
+ "/Promotion/GetOfflineCouponConsumePageList": "/Promotion/GetOfflineCouponConsumePageList",
+ "/Order/GetRefundPayLogList": None,
+ # 已知特殊
+ "/Site/GetAllOrderSettleList": "/Site/GetFormerOrderSettleList",
+ "/PayLog/GetPayLogListPage": "/PayLog/GetFormerPayLogListPage",
+}
+
+
+TIME_WINDOW_KEYS: tuple[tuple[str, str], ...] = (
+ ("startTime", "endTime"),
+ ("rangeStartTime", "rangeEndTime"),
+ ("StartPayTime", "EndPayTime"),
+)
+
+
+@dataclass(frozen=True)
+class WindowSpec:
+ start_key: str
+ end_key: str
+ start: datetime
+ end: datetime
+
+
+@dataclass(frozen=True)
+class RoutedCall:
+ endpoint: str
+ params: dict
+
+
+def is_former_endpoint(endpoint: str) -> bool:
+ return "Former" in str(endpoint or "")
+
+
+def _parse_dt(value: object, tz: ZoneInfo) -> datetime | None:
+ if value is None:
+ return None
+ s = str(value).strip()
+ if not s:
+ return None
+ dt = dtparser.parse(s)
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=tz)
+ return dt.astimezone(tz)
+
+
+def _fmt_dt(dt: datetime, tz: ZoneInfo) -> str:
+ return dt.astimezone(tz).strftime("%Y-%m-%d %H:%M:%S")
+
+
+def extract_window_spec(params: dict | None, tz: ZoneInfo = ROUTING_TZ) -> WindowSpec | None:
+ if not isinstance(params, dict) or not params:
+ return None
+ for start_key, end_key in TIME_WINDOW_KEYS:
+ if start_key in params or end_key in params:
+ start = _parse_dt(params.get(start_key), tz)
+ end = _parse_dt(params.get(end_key), tz)
+ if start and end:
+ return WindowSpec(start_key=start_key, end_key=end_key, start=start, end=end)
+ return None
+
+
+def derive_former_endpoint(recent_endpoint: str) -> str | None:
+ endpoint = str(recent_endpoint or "").strip()
+ if not endpoint:
+ return None
+
+ if endpoint in RECENT_TO_FORMER_OVERRIDES:
+ return RECENT_TO_FORMER_OVERRIDES[endpoint]
+
+ if is_former_endpoint(endpoint):
+ return endpoint
+
+ idx = endpoint.find("Get")
+ if idx == -1:
+ return endpoint
+ return f"{endpoint[:idx]}GetFormer{endpoint[idx + 3:]}"
+
+
+def recent_boundary(now: datetime, months: int = RECENT_MONTHS) -> datetime:
+ """
+ 3个月(自然月)边界:取 (now - months) 所在月份的 1 号 00:00:00。
+ """
+ if now.tzinfo is None:
+ raise ValueError("now 必须为时区时间")
+ base = now - relativedelta(months=months)
+ return base.replace(day=1, hour=0, minute=0, second=0, microsecond=0)
+
+
+def plan_calls(
+ endpoint: str,
+ params: dict | None,
+ *,
+ now: datetime | None = None,
+ tz: ZoneInfo = ROUTING_TZ,
+ months: int = RECENT_MONTHS,
+) -> list[RoutedCall]:
+ """
+ 根据 endpoint + params 的时间窗口,返回要调用的 endpoint/params 列表(可能拆分为两段)。
+ """
+ base_params = dict(params or {})
+ if not base_params:
+ return [RoutedCall(endpoint=endpoint, params=base_params)]
+
+ # 若调用方显式传了 Former 接口,则不二次路由。
+ if is_former_endpoint(endpoint):
+ return [RoutedCall(endpoint=endpoint, params=base_params)]
+
+ window = extract_window_spec(base_params, tz)
+ if not window:
+ return [RoutedCall(endpoint=endpoint, params=base_params)]
+
+ former_endpoint = derive_former_endpoint(endpoint)
+ if former_endpoint is None or former_endpoint == endpoint:
+ return [RoutedCall(endpoint=endpoint, params=base_params)]
+
+ now_dt = (now or datetime.now(tz)).astimezone(tz)
+ boundary = recent_boundary(now_dt, months=months)
+
+ start, end = window.start, window.end
+ if end <= boundary:
+ return [RoutedCall(endpoint=former_endpoint, params=base_params)]
+ if start >= boundary:
+ return [RoutedCall(endpoint=endpoint, params=base_params)]
+
+ # 跨越边界:拆分两段(老数据 -> former,新数据 -> recent)
+ p1 = dict(base_params)
+ p1[window.start_key] = _fmt_dt(start, tz)
+ p1[window.end_key] = _fmt_dt(boundary, tz)
+
+ p2 = dict(base_params)
+ p2[window.start_key] = _fmt_dt(boundary, tz)
+ p2[window.end_key] = _fmt_dt(end, tz)
+
+ return [RoutedCall(endpoint=former_endpoint, params=p1), RoutedCall(endpoint=endpoint, params=p2)]
+
diff --git a/etl_billiards/api/local_json_client.py b/etl_billiards/api/local_json_client.py
index ce30836..8d752c3 100644
--- a/etl_billiards/api/local_json_client.py
+++ b/etl_billiards/api/local_json_client.py
@@ -20,6 +20,10 @@ class LocalJsonClient:
if not self.base_dir.exists():
raise FileNotFoundError(f"JSON 目录不存在: {self.base_dir}")
+ def get_source_hint(self, endpoint: str) -> str:
+ """Return the JSON file path for this endpoint (for source_file lineage)."""
+ return str(self.base_dir / endpoint_to_filename(endpoint))
+
def iter_paginated(
self,
endpoint: str,
diff --git a/etl_billiards/api/recording_client.py b/etl_billiards/api/recording_client.py
index f8659b1..187abf5 100644
--- a/etl_billiards/api/recording_client.py
+++ b/etl_billiards/api/recording_client.py
@@ -7,6 +7,7 @@ from pathlib import Path
from typing import Any, Iterable, Tuple
from api.client import APIClient
+from api.endpoint_routing import plan_calls
from utils.json_store import dump_json, endpoint_to_filename
@@ -33,6 +34,10 @@ class RecordingAPIClient:
self.last_dump: dict[str, Any] | None = None
# ------------------------------------------------------------------ public API
+ def get_source_hint(self, endpoint: str) -> str:
+ """Return the JSON dump path for this endpoint (for source_file lineage)."""
+ return str(self.output_dir / endpoint_to_filename(endpoint))
+
def iter_paginated(
self,
endpoint: str,
@@ -99,11 +104,18 @@ class RecordingAPIClient:
):
filename = endpoint_to_filename(endpoint)
path = self.output_dir / filename
+ routing_calls = []
+ try:
+ for call in plan_calls(endpoint, params):
+ routing_calls.append({"endpoint": call.endpoint, "params": call.params})
+ except Exception:
+ routing_calls = []
payload = {
"task_code": self.task_code,
"run_id": self.run_id,
"endpoint": endpoint,
"params": params or {},
+ "endpoint_routing": {"calls": routing_calls} if routing_calls else None,
"page_size": page_size,
"pages": pages,
"total_records": total_records,
diff --git a/etl_billiards/build_exe.py b/etl_billiards/build_exe.py
new file mode 100644
index 0000000..dfed3af
--- /dev/null
+++ b/etl_billiards/build_exe.py
@@ -0,0 +1,181 @@
+# -*- coding: utf-8 -*-
+"""
+ETL GUI 打包脚本
+
+使用 PyInstaller 将 GUI 应用打包为 Windows EXE
+
+用法:
+ python build_exe.py [--onefile] [--console] [--clean]
+
+参数:
+ --onefile 打包为单个 EXE 文件(默认为目录模式)
+ --console 显示控制台窗口(调试用)
+ --clean 打包前清理旧的构建文件
+"""
+
+import os
+import sys
+import shutil
+import subprocess
+from pathlib import Path
+
+
+def get_project_root() -> Path:
+ """获取项目根目录"""
+ return Path(__file__).resolve().parent
+
+
+def clean_build():
+ """清理旧的构建文件"""
+ project_root = get_project_root()
+
+ dirs_to_clean = [
+ project_root / "build",
+ project_root / "dist",
+ ]
+
+ files_to_clean = [
+ project_root / "etl_gui.spec",
+ ]
+
+ for d in dirs_to_clean:
+ if d.exists():
+ print(f"清理目录: {d}")
+ shutil.rmtree(d)
+
+ for f in files_to_clean:
+ if f.exists():
+ print(f"清理文件: {f}")
+ f.unlink()
+
+
+def build_exe(onefile: bool = False, console: bool = False):
+ """构建 EXE"""
+ project_root = get_project_root()
+
+ # 主入口
+ main_script = project_root / "gui" / "main.py"
+
+ # 资源文件
+ resources_dir = project_root / "gui" / "resources"
+ database_dir = project_root / "database"
+
+ # 构建 PyInstaller 命令
+ # 使用 ASCII 名称避免 Windows 控制台编码问题
+ cmd = [
+ sys.executable, "-m", "PyInstaller",
+ "--name", "ETL_Manager",
+ "--noconfirm",
+ ]
+
+ # 单文件或目录模式
+ if onefile:
+ cmd.append("--onefile")
+ else:
+ cmd.append("--onedir")
+
+ # 窗口模式
+ if not console:
+ cmd.append("--windowed")
+
+ # 添加数据文件
+ # 样式表
+ if resources_dir.exists():
+ cmd.extend(["--add-data", f"{resources_dir};gui/resources"])
+
+ # 数据库 SQL 文件
+ if database_dir.exists():
+ for sql_file in database_dir.glob("*.sql"):
+ cmd.extend(["--add-data", f"{sql_file};database"])
+
+ # 隐式导入
+ hidden_imports = [
+ "PySide6.QtCore",
+ "PySide6.QtGui",
+ "PySide6.QtWidgets",
+ "psycopg2",
+ "psycopg2.extras",
+ "psycopg2.extensions",
+ # GUI 模块
+ "gui.models.task_model",
+ "gui.models.schedule_model",
+ "gui.utils.cli_builder",
+ "gui.utils.config_helper",
+ "gui.utils.app_settings",
+ "gui.workers.task_worker",
+ "gui.workers.db_worker",
+ "gui.widgets.settings_dialog",
+ ]
+ for imp in hidden_imports:
+ cmd.extend(["--hidden-import", imp])
+
+ # 排除不需要的模块(减小体积)
+ excludes = [
+ "matplotlib",
+ "numpy",
+ "pandas",
+ "scipy",
+ "PIL",
+ "cv2",
+ "tkinter",
+ ]
+ for exc in excludes:
+ cmd.extend(["--exclude-module", exc])
+
+ # 工作目录
+ cmd.extend(["--workpath", str(project_root / "build")])
+ cmd.extend(["--distpath", str(project_root / "dist")])
+ cmd.extend(["--specpath", str(project_root)])
+
+ # 主脚本
+ cmd.append(str(main_script))
+
+ print("执行命令:")
+ print(" ".join(cmd))
+ print()
+
+ # 执行打包
+ result = subprocess.run(cmd, cwd=str(project_root))
+
+ if result.returncode == 0:
+ print()
+ print("=" * 50)
+ print("打包成功!")
+ print(f"输出目录: {project_root / 'dist'}")
+ print("=" * 50)
+ else:
+ print()
+ print("打包失败,请检查错误信息")
+ sys.exit(1)
+
+
+def main():
+ """主函数"""
+ import argparse
+
+ parser = argparse.ArgumentParser(description="ETL GUI 打包工具")
+ parser.add_argument("--onefile", action="store_true", help="打包为单个 EXE")
+ parser.add_argument("--console", action="store_true", help="显示控制台窗口")
+ parser.add_argument("--clean", action="store_true", help="打包前清理")
+
+ args = parser.parse_args()
+
+ # 检查 PyInstaller
+ try:
+ import PyInstaller
+ print(f"PyInstaller 版本: {PyInstaller.__version__}")
+ except ImportError:
+ print("错误: 未安装 PyInstaller")
+ print("请运行: pip install pyinstaller")
+ sys.exit(1)
+
+ # 清理
+ if args.clean:
+ clean_build()
+
+ # 构建
+ build_exe(onefile=args.onefile, console=args.console)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/etl_billiards/cli/main.py b/etl_billiards/cli/main.py
index 3c2bd23..3fea875 100644
--- a/etl_billiards/cli/main.py
+++ b/etl_billiards/cli/main.py
@@ -40,6 +40,34 @@ def parse_args():
parser.add_argument("--api-timeout", type=int, help="API超时(秒)")
parser.add_argument("--api-page-size", type=int, help="分页大小")
parser.add_argument("--api-retry-max", type=int, help="API重试最大次数")
+
+ # 回溯/手动窗口
+ parser.add_argument(
+ "--window-start",
+ dest="window_start",
+ help="固定时间窗口开始(优先级高于游标,例如:2025-07-01 00:00:00)",
+ )
+ parser.add_argument(
+ "--window-end",
+ dest="window_end",
+ help="固定时间窗口结束(优先级高于游标,推荐用月末+1,例如:2025-08-01 00:00:00)",
+ )
+ parser.add_argument(
+ "--force-window-override",
+ action="store_true",
+ help="强制使用 window_start/window_end,不走 MAX(fetched_at) 兜底",
+ )
+ parser.add_argument(
+ "--window-split-unit",
+ dest="window_split_unit",
+ help="窗口切分单位(month/none),默认来自配置 run.window_split.unit",
+ )
+ parser.add_argument(
+ "--window-compensation-hours",
+ dest="window_compensation_hours",
+ type=int,
+ help="窗口前后补偿小时数,默认来自配置 run.window_split.compensation_hours",
+ )
# 目录参数
parser.add_argument("--export-root", help="导出根目录")
@@ -108,6 +136,22 @@ def build_cli_overrides(args) -> dict:
if args.write_pretty_json:
overrides.setdefault("io", {})["write_pretty_json"] = True
+ # 回溯/手动窗口
+ if args.window_start or args.window_end:
+ overrides.setdefault("run", {}).setdefault("window_override", {})
+ if args.window_start:
+ overrides["run"]["window_override"]["start"] = args.window_start
+ if args.window_end:
+ overrides["run"]["window_override"]["end"] = args.window_end
+ if args.force_window_override:
+ overrides.setdefault("run", {})["force_window_override"] = True
+ if args.window_split_unit:
+ overrides.setdefault("run", {}).setdefault("window_split", {})["unit"] = args.window_split_unit
+ if args.window_compensation_hours is not None:
+ overrides.setdefault("run", {}).setdefault("window_split", {})[
+ "compensation_hours"
+ ] = args.window_compensation_hours
+
# 运行窗口
if args.idle_start:
overrides.setdefault("run", {}).setdefault("idle_window", {})["start"] = args.idle_start
diff --git a/etl_billiards/config/defaults.py b/etl_billiards/config/defaults.py
index dfe57af..1aab083 100644
--- a/etl_billiards/config/defaults.py
+++ b/etl_billiards/config/defaults.py
@@ -58,6 +58,10 @@ DEFAULTS = {
"default_idle": 180,
},
"overlap_seconds": 120,
+ "window_split": {
+ "unit": "month",
+ "compensation_hours": 2,
+ },
"idle_window": {
"start": "04:00",
"end": "16:00",
@@ -65,8 +69,8 @@ DEFAULTS = {
"allow_empty_result_advance": True,
},
"io": {
- "export_root": r"C:\dev\LLTQ\export\JSON",
- "log_root": r"C:\dev\LLTQ\export\LOG",
+ "export_root": "export/JSON",
+ "log_root": "export/LOG",
"manifest_name": "manifest.json",
"ingest_report_name": "ingest_report.json",
"write_pretty_json": True,
@@ -76,7 +80,7 @@ DEFAULTS = {
# 运行流程:FETCH_ONLY(仅在线抓取落盘)、INGEST_ONLY(本地清洗入库)、FULL(抓取 + 清洗入库)
"flow": "FULL",
# 在线抓取 JSON 输出根目录(按任务、run_id 与时间自动创建子目录)
- "fetch_root": r"C:\dev\LLTQ\export\JSON",
+ "fetch_root": "export/JSON",
# 本地清洗入库时的 JSON 输入目录(为空则默认使用本次抓取目录)
"ingest_source_dir": "",
},
@@ -97,10 +101,19 @@ DEFAULTS = {
},
"ods": {
# ODS 离线重建/回放相关(仅开发/运维使用)
- "json_doc_dir": r"C:\dev\LLTQ\export\test-json-doc",
+ "json_doc_dir": "export/test-json-doc",
"include_files": "",
"drop_schema_first": True,
},
+ "integrity": {
+ "mode": "history",
+ "history_start": "2025-07-01",
+ "history_end": "",
+ "include_dimensions": False,
+ "auto_check": False,
+ "ods_task_codes": "",
+ },
+
}
# 任务代码常量
diff --git a/etl_billiards/config/env_parser.py b/etl_billiards/config/env_parser.py
index 2ec2553..1b1aee5 100644
--- a/etl_billiards/config/env_parser.py
+++ b/etl_billiards/config/env_parser.py
@@ -40,11 +40,22 @@ ENV_MAP = {
"IDLE_WINDOW_END": ("run.idle_window.end",),
"ALLOW_EMPTY_RESULT_ADVANCE": ("run.allow_empty_result_advance",),
"ALLOW_EMPTY_ADVANCE": ("run.allow_empty_result_advance",),
+ "WINDOW_START": ("run.window_override.start",),
+ "WINDOW_END": ("run.window_override.end",),
+ "WINDOW_SPLIT_UNIT": ("run.window_split.unit",),
+ "WINDOW_COMPENSATION_HOURS": ("run.window_split.compensation_hours",),
"PIPELINE_FLOW": ("pipeline.flow",),
"JSON_FETCH_ROOT": ("pipeline.fetch_root",),
"JSON_SOURCE_DIR": ("pipeline.ingest_source_dir",),
"FETCH_ROOT": ("pipeline.fetch_root",),
"INGEST_SOURCE_DIR": ("pipeline.ingest_source_dir",),
+ "INTEGRITY_MODE": ("integrity.mode",),
+ "INTEGRITY_HISTORY_START": ("integrity.history_start",),
+ "INTEGRITY_HISTORY_END": ("integrity.history_end",),
+ "INTEGRITY_INCLUDE_DIMENSIONS": ("integrity.include_dimensions",),
+ "INTEGRITY_AUTO_CHECK": ("integrity.auto_check",),
+ "INTEGRITY_AUTO_BACKFILL": ("integrity.auto_backfill",),
+ "INTEGRITY_ODS_TASK_CODES": ("integrity.ods_task_codes",),
}
diff --git a/etl_billiards/database/operations.py b/etl_billiards/database/operations.py
index ec48c0d..d9b6f3f 100644
--- a/etl_billiards/database/operations.py
+++ b/etl_billiards/database/operations.py
@@ -25,46 +25,54 @@ class DatabaseOperations:
use_returning = "RETURNING" in sql.upper()
- with self.conn.cursor() as c:
- if not use_returning:
+ # 不带 RETURNING:直接批量执行即可
+ if not use_returning:
+ with self.conn.cursor() as c:
psycopg2.extras.execute_batch(c, sql, rows, page_size=page_size)
- return (0, 0)
-
- # 尝试向量化执行
+ return (0, 0)
+
+ # 尝试向量化执行(execute_values + fetch returning)
+ vectorized_failed = False
+ m = re.search(r"VALUES\s*\((.*?)\)", sql, flags=re.IGNORECASE | re.DOTALL)
+ if m:
+ tpl = "(" + m.group(1) + ")"
+ base_sql = sql[:m.start()] + "VALUES %s" + sql[m.end():]
try:
- m = re.search(r"VALUES\s*\((.*?)\)", sql, flags=re.IGNORECASE | re.DOTALL)
- if m:
- tpl = "(" + m.group(1) + ")"
- base_sql = sql[:m.start()] + "VALUES %s" + sql[m.end():]
-
+ with self.conn.cursor() as c:
ret = psycopg2.extras.execute_values(
c, base_sql, rows, template=tpl, page_size=page_size, fetch=True
)
-
- if not ret:
- return (0, 0)
-
- inserted = sum(1 for rec in ret if self._is_inserted(rec))
- return (inserted, len(ret) - inserted)
+ if not ret:
+ return (0, 0)
+ inserted = sum(1 for rec in ret if self._is_inserted(rec))
+ return (inserted, len(ret) - inserted)
+ except Exception:
+ # 向量化失败后,事务通常处于 aborted 状态,需要先 rollback 才能继续执行。
+ vectorized_failed = True
+
+ if vectorized_failed:
+ try:
+ self.conn.rollback()
except Exception:
pass
-
- # 回退:逐行执行
- inserted = 0
- updated = 0
+
+ # 回退:逐行执行
+ inserted = 0
+ updated = 0
+ with self.conn.cursor() as c:
for r in rows:
c.execute(sql, r)
try:
rec = c.fetchone()
except Exception:
rec = None
-
+
if self._is_inserted(rec):
inserted += 1
else:
updated += 1
-
- return (inserted, updated)
+
+ return (inserted, updated)
@staticmethod
def _is_inserted(rec) -> bool:
diff --git a/etl_billiards/database/schema_ODS_doc.sql b/etl_billiards/database/schema_ODS_doc.sql
new file mode 100644
index 0000000..d194c25
--- /dev/null
+++ b/etl_billiards/database/schema_ODS_doc.sql
@@ -0,0 +1,1945 @@
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS 'ODS 原始明细表:会员档案/会员账户信息。来源:export/test-json-doc/member_profiles.json;分析:member_profiles-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '【说明】会员的注册门店 ID。 【示例】2790685415443269(用于会员的注册门店 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '【说明】注册门店名称,属于冗余字段,用于直接展示。 【示例】朗朗桌球(注册门店名称,属于冗余字段,用于直接展示)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - site_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '【说明】这是“租户内会员账户”的主键 ID。 【示例】2955204541320325(用于这是“租户内会员账户”的主键 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '【说明】这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。 【示例】2955204540009605(用于这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '【说明】这两个字段是成对出现的:一个数值码,一个中文名称。 【示例】2790683528022853(用于这两个字段是成对出现的:一个数值码,一个中文名称)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '【说明】这是“会员卡种类/等级”的定义字段。 【示例】储值卡(用于这是“会员卡种类/等级”的定义字段)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '【说明】会员绑定的手机号码。 【示例】18620043391(用于会员绑定的手机号码)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - mobile。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '【说明】会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。 【示例】胡先生(用于会员在当前租户下的显示名称(可以是姓名,也可以是昵称))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - nickname。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '【说明】当前积分余额(这条会员账户的积分值)。 【示例】0.0(用于当前积分余额(这条会员账户的积分值))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - point。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '【说明】成长值 / 经验值,用于会员等级晋升的累计指标。 【示例】0.0(成长值 / 经验值,用于会员等级晋升的累计指标)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - growth_value。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '【说明】推荐人会员 ID,用于记录该会员是由哪位老会员推荐。 【示例】0(推荐人会员 ID,用于记录该会员是由哪位老会员推荐)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - referrer_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '【说明】帐户状态(偏“卡状态/档案状态”)。 【示例】1(用于帐户状态(偏“卡状态/档案状态”))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '【说明】用户账号状态(偏“用户逻辑”层面的状态)。 【示例】1(用于用户账号状态(偏“用户逻辑”层面的状态))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - user_status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '【说明】会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。 【示例】2025-11-08 01:29:33(用于会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_profiles.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_profiles.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS 'ODS 原始明细表:会员余额变更流水。来源:export/test-json-doc/member_balance_changes.json;分析:member_balance_changes-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '【说明】租户/商户 ID,本数据中是固定值(同一品牌/商户)。 【示例】2790683160709957(用于租户/商户 ID,本数据中是固定值(同一品牌/商户))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '【说明】非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致)。 【示例】2790685415443269(用于非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '【说明】会员卡的“注册门店 ID”,即办卡所在门店。 【示例】2790685415443269(用于会员卡的“注册门店 ID”,即办卡所在门店)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '【说明】卡片的注册门店名称(办卡地点),和 register_site_id 配套。 【示例】朗朗桌球(用于卡片的注册门店名称(办卡地点),和 register_site_id 配套)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - registerSiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '【说明】发生本次余额变更的门店名称(即本次消费/充值所在门店)。 【示例】朗朗桌球(用于发生本次余额变更的门店名称(即本次消费/充值所在门店))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - paySiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '【说明】余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。 【示例】2957881605869253(用于余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '【说明】商户维度的会员 ID(租户内会员主键)。 【示例】2799212845565701(用于商户维度的会员 ID(租户内会员主键))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '【说明】会员卡账户 ID,在租户内唯一标识某张卡。 【示例】2799219999295237(用于会员卡账户 ID,在租户内唯一标识某张卡)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_card_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '【说明】系统级(全局)会员 ID。 【示例】2799212844549893(用于系统级(全局)会员 ID)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '【说明】会员姓名或称呼(非昵称字段)。 【示例】曾丹烨(用于会员姓名或称呼(非昵称字段))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '【说明】会员手机号。 【示例】13922213242(用于会员手机号)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberMobile。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '【说明】卡种类型 ID,用于区分不同卡种。 【示例】2793249295533893(卡种类型 ID,用于区分不同卡种)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '【说明】卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。 【示例】储值卡(用于卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberCardTypeName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '【说明】本次变动的金额(元),正数表示增加,负数表示减少。 【示例】-120.0(用于本次变动的金额(元),正数表示增加,负数表示减少)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - account_data。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '【说明】本次变动前,该卡账户的余额(元)。 【示例】816.3(用于本次变动前,该卡账户的余额(元))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - before。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '【说明】本次变动后,该卡账户的余额(元)。 【示例】696.3(用于本次变动后,该卡账户的余额(元))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - after。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '【说明】可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。 【示例】0.0(可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - refund_amount。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - from_type。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - payment_method。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '【说明】例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。 【示例】2957881518788421(用于例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - relate_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '【说明】当为空时,说明这条变动没有额外备注说明。 【示例】充值退款(用于当为空时,说明这条变动没有额外备注说明)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - remark。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '【说明】执行此次余额变更操作的员工 ID。 【示例】2790687322443013(用于执行此次余额变更操作的员工 ID)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '【说明】操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。 【示例】收银员:郑丽珊(用于操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_name。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - is_delete。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '【说明】本条余额变更记录的创建时间,通常接近交易发生时间。 【示例】2025-11-09 22:52:48(用于本条余额变更记录的创建时间,通常接近交易发生时间)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - create_time。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_balance_changes.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_balance_changes.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS 'ODS 原始明细表:会员储值/卡券账户列表。来源:export/test-json-doc/member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '【说明】租户/品牌 ID,与其他 JSON 中 tenant_id 一致。 【示例】2790683160709957(用于租户/品牌 ID,与其他 JSON 中 tenant_id 一致)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '【说明】当前商户(品牌/租户)中会员的主键 ID。 【示例】2955204541320325(用于当前商户(品牌/租户)中会员的主键 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '【说明】系统级会员 ID(跨门店统一主键)。 【示例】2955204540009605(用于系统级会员 ID(跨门店统一主键))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '【说明】卡首次办理的门店 ID。 【示例】2790685415443269(用于卡首次办理的门店 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '【说明】卡归属门店名称(视图中的展示字段)。 【示例】朗朗桌球(用于卡归属门店名称(视图中的展示字段))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - site_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2955206162843781(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '【说明】卡等级/卡类代码,和下面两个名称字段一一对应。 【示例】2790683528022856(用于卡等级/卡类代码,和下面两个名称字段一一对应)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '【说明】卡等级/卡类名称。 【示例】活动抵用券(用于卡等级/卡类名称)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '【说明】卡类型名称,实际与 member_card_grade_code_name 一致。 【示例】活动抵用券(用于卡类型名称,实际与 member_card_grade_code_name 一致)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_type_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '【说明】持卡会员姓名快照。 【示例】胡先生(用于持卡会员姓名快照)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '【说明】持卡会员手机号快照。 【示例】18620043391(用于持卡会员手机号快照)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_mobile。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '【说明】卡种 ID(定义“这是哪一种卡”)。 【示例】2793266846533445(用于卡种 ID(定义“这是哪一种卡”))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '【说明】实体卡物理卡号/条码号。 【示例】NULL(用于实体卡物理卡号/条码号)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_no。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '【说明】物理卡类型。 【示例】1(用于物理卡类型)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_physics_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '【说明】当前卡内余额(主要针对储值卡、部分券卡)。 【示例】0.0(用于当前卡内余额(主要针对储值卡、部分券卡))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - balance。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '【说明】采用“几折”的记法:10=不打折,9=九折,8=八折。 【示例】0.0(用于采用“几折”的记法:10=不打折,9=九折,8=八折)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - denomination。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCarDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '【说明】助教奖励金方向扣款的配置。 【示例】0.0(用于助教奖励金方向扣款的配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantRewardCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '【说明】结算时从卡中扣除的金额上限/规则配置(视图级。 【示例】0.0(用于结算时从卡中扣除的金额上限/规则配置(视图级)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cardSettleDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '【说明】与卡绑定的“券额度扣除配置”。 【示例】0.0(用于与卡绑定的“券额度扣除配置”)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - couponCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '【说明】配送费可否/多少从卡中抵扣,目前无业务发生。 【示例】0.0(用于配送费可否/多少从卡中抵扣,目前无业务发生)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - deliveryFeeDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '【说明】卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。 【示例】NULL(用于卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - use_scene。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '【说明】是否允许跨店使用。 【示例】1(用于是否允许跨店使用)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_cross_site。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】NULL(布尔/开关字段,用于表示权限、可用性或状态开关)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '【说明】是否允许转赠/转让给其他会员。 【示例】0(用于是否允许转赠/转让给其他会员)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_give。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '【说明】是否允许在“订单层面统一扣款”。 【示例】0(用于是否允许在“订单层面统一扣款”)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_order_deduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_delete。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '【说明】卡绑定密码,用于消费或查询验证(目前未启用)。 【示例】NULL(卡绑定密码,用于消费或查询验证(目前未启用))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - bind_password。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_range_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '【说明】可用的商品分类 ID 列表。 【示例】[](用于可用的商品分类 ID 列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '【说明】限定可使用的台区 ID 列表。 【示例】[](用于限定可使用的台区 ID 列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableAreaId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '【说明】卡片限定生效门店 ID。 【示例】0(用于卡片限定生效门店 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - effect_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '【说明】卡片生效开始时间(有效期起始)。 【示例】2025-11-08 01:31:12(用于卡片生效开始时间(有效期起始))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '【说明】卡片有效期结束时间。 【示例】2225-01-01 00:00:00(用于卡片有效期结束时间)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '【说明】最近一次消费时间。 【示例】2025-11-09 07:48:23(用于最近一次消费时间)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - last_consume_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '【说明】卡片创建时间(开卡时间)。 【示例】2025-11-08 01:31:12(用于卡片创建时间(开卡时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - create_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '【说明】状态枚举,用于标识记录当前业务状态。 【示例】1(状态枚举,用于标识记录当前业务状态。)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - status。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '【说明】在前端展示或某些列表中的排序权重。 【示例】1(用于在前端展示或某些列表中的排序权重)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - sort。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '【说明】品牌头像 URL(未配置)。 【示例】NULL(用于品牌头像 URL(未配置))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantAvatar。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '【说明】租户/品牌名称(当前导出为空)。 【示例】NULL(用于租户/品牌名称(当前导出为空))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantName。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '【说明】允许使用的“陪打/助教等级”列表。 【示例】[](用于允许使用的“陪打/助教等级”列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - pdAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '【说明】可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写)。 【示例】[](用于可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cxAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_stored_value_cards.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_stored_value_cards.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS 'ODS 原始明细表:充值结算记录。来源:export/test-json-doc/recharge_settlements.json;分析:recharge_settlements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - siteid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - sitename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - createtime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - memberid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - membername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tableid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - payamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - settlename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settletype。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - paytime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - canberevoked。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isusecoupon。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - isusediscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isactivity。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】recharge_settlements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/recharge_settlements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】recharge_settlements.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS 'ODS 原始明细表:结账/结算记录。来源:export/test-json-doc/settlement_records.json;分析:settlement_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '【说明】结账记录主键 ID(订单结算 ID)。 【示例】NULL(用于结账记录主键 ID(订单结算 ID))。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - siteid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - sitename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - createtime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - memberid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - membername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tableid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - payamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - settlename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settletype。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - paytime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - canberevoked。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isusecoupon。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - isusediscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isactivity。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】settlement_records.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS 'ODS 原始明细表:助教作废/取消记录。来源:export/test-json-doc/assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2957675849518789(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '【说明】门店 ID,即该废除记录所在门店。 【示例】2790685415443269(用于门店 ID,即该废除记录所在门店)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '【说明】助教姓名/对外展示名称。 【示例】泡芙(用于助教姓名/对外展示名称)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '【说明】与“助教废除”关联的金额字段。 【示例】5.83(用于与“助教废除”关联的金额字段)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantAbolishAmount。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '【说明】助教编号(工号/序号)。 【示例】27(用于助教编号(工号/序号))。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantOn。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '【说明】“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟。 【示例】214(用于“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - pdChargeMinutes。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '【说明】台桌所在区域 ID。 【示例】2791963816579205(用于台桌所在区域 ID)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableAreaId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '【说明】台桌所属区域名称。 【示例】C区(用于台桌所属区域名称)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableArea。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '【说明】球台/桌子的 ID。 【示例】2793016660660357(用于球台/桌子的 ID)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '【说明】台桌名称/编号,供人阅读。 【示例】C1(用于台桌名称/编号,供人阅读)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '【说明】用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等。 【示例】NULL(用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - trashReason。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '【说明】这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻。 【示例】2025-11-09 19:23:29(用于这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - createTime。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_cancellation_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_cancellation_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ birth_date TIMESTAMP,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ last_update_name TEXT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS 'ODS 原始明细表:助教档案主数据。来源:export/test-json-doc/assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '【说明】助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。 【示例】2947562271297029(用于助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '【说明】品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。 【示例】2790683160709957(用于品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '【说明】门店 ID,对应本次数据的这家球房(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,对应本次数据的这家球房(朗朗桌球))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '【说明】助教工号 / 编号,便于业务侧识别。 【示例】31(用于助教工号 / 编号,便于业务侧识别)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '【说明】助教在前台展示的昵称,如“佳怡”“周周”“球球”等。 【示例】小然(用于助教在前台展示的昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '【说明】助教真实姓名,如“何海婷”“梁婷婷”等。 【示例】张静然(用于助教真实姓名,如“何海婷”“梁婷婷”等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - real_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '【说明】助教手机号,用于登录绑定、通知、钉钉同步等。 【示例】15119679931(助教手机号,用于登录绑定、通知、钉钉同步等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - mobile。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '【说明】团队名称,展示用,和 team_id 一一对应。 【示例】1组(用于团队名称,展示用,和 team_id 一一对应)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '【说明】系统级“用户账号 ID”,通常对应登录账号。 【示例】2947562270838277(用于系统级“用户账号 ID”,通常对应登录账号)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '【说明】10 × 24。 【示例】20(用于10 × 24)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - level。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '【说明】1 × 48。 【示例】1(用于1 × 48)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '【说明】当 leave_status = 0 时,work_status = 1。 【示例】2(用于当 leave_status = 0 时,work_status = 1)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - work_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '【说明】0 × 21。 【示例】1(用于0 × 21)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - leave_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '【说明】入职时间。 【示例】2025-11-02 08:00:00(用于入职时间)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '【说明】离职日期。 【示例】2025-11-03 08:00:00(用于离职日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '【说明】当前配置生效的开始日期。 【示例】2025-11-01 08:00:00(用于当前配置生效的开始日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '【说明】当前配置生效的结束日期(例如一个周期性的排班/合同周期)。 【示例】2025-12-01 08:00:00(用于当前配置生效的结束日期(例如一个周期性的排班/合同周期))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '【说明】账号创建时间。 【示例】2025-11-02 15:55:26(用于账号创建时间)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '【说明】账号最近一次被修改的时间(例如修改等级、昵称等)。 【示例】2025-11-03 18:32:07(用于账号最近一次被修改的时间(例如修改等级、昵称等))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - update_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '【说明】该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。 【示例】0(该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '【说明】预留给“人事系统员工 ID”的字段,目前未接入或未启用。 【示例】0(用于预留给“人事系统员工 ID”的字段,目前未接入或未启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '【说明】人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。 【示例】0(用于人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_profile_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】10(标识类 ID 字段,用于关联/定位相关实体)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - system_role_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '【说明】助教头像地址。 【示例】https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(用于助教头像地址)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - avatar。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.birth_date IS '【说明】助教出生日期。 【示例】0001-01-01 00:00:00(用于助教出生日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - birth_date。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '【说明】0 × 40。 【示例】0(用于0 × 40)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - gender。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '【说明】身高(单位:厘米)。 【示例】0.0(用于身高(单位:厘米))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - height。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '【说明】体重(单位:公斤)。 【示例】0.0(用于体重(单位:公斤))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - weight。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '【说明】备用工号字段,目前未在该门店启用。 【示例】NULL(用于备用工号字段,目前未在该门店启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - job_num。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '【说明】前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。 【示例】31(用于前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_sort。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '【说明】评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。 【示例】0.0(评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '【说明】助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分。 【示例】0.0(用于助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '【说明】累计被评分次数。 【示例】0(用于累计被评分次数)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '【说明】个人简介文案,预留给助教自我介绍使用。 【示例】NULL(用于个人简介文案,预留给助教自我介绍使用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - introduce。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '【说明】助教个人视频介绍地址。 【示例】https://oss.ficoo.vip/cbb/userVideo/1753096246308/175309624630830.mp4(用于助教个人视频介绍地址)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - video_introduction_url。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '【说明】上层“分组 ID”预留字段(例如集团/事业部),本门店未使用。 【示例】0(用于上层“分组 ID”预留字段(例如集团/事业部),本门店未使用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '【说明】group_id 对应的名称,目前为空。 【示例】NULL(用于group_id 对应的名称,目前为空)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '【说明】门店名称,冗余字段,用于展示。 【示例】朗朗桌球(门店名称,冗余字段,用于展示)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - shop_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '【说明】2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现。 【示例】2(用于2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - charge_way。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_type。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - allow_cx。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_guaranteed。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - salary_grant_enabled。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '【说明】灯光控制状态,如 1=启用控制、2=不启用 或相反。 【示例】2(用于灯光控制状态,如 1=启用控制、2=不启用 或相反)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '【说明】在线状态。 【示例】1(用于在线状态)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - online_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '【说明】促销时段的单价,本门店未在账号表层面设置。 【示例】0.0(用于促销时段的单价,本门店未在账号表层面设置)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - cx_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '【说明】某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中)。 【示例】0.0(用于某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - pd_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '【说明】该助教最近一次服务的球台 ID。 【示例】0(用于该助教最近一次服务的球台 ID)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '【说明】最近服务球台名称(展示用)。 【示例】TV(用于最近服务球台名称(展示用))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '【说明】人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织。 【示例】2947562271215109(用于人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '【说明】系统内部生成的序列号或排序标识,用于全局排序或迁移。 【示例】0(系统内部生成的序列号或排序标识,用于全局排序或迁移)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - serial_number。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_team_leader。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '【说明】1 × 49。 【示例】1(用于1 × 49)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - criticism_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_update_name IS '【说明】最近修改该账号配置的管理员名称。 【示例】管理员:郑丽珊(用于最近修改该账号配置的管理员名称)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_update_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - ding_talk_synced。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '【说明】门店灯控配置 ID,本门店未在助教账号维度启用。 【示例】0(用于门店灯控配置 ID,本门店未在助教账号维度启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_light_cfg_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '【说明】灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件。 【示例】NULL(用于灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_equipment_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '【说明】离职协议签署状态,类似上面。 【示例】0(用于离职协议签署状态,类似上面)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_accounts_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_accounts_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ levelname TEXT,
+ site_assistant_id BIGINT,
+ skill_id BIGINT,
+ skillname TEXT,
+ system_member_id BIGINT,
+ tablename TEXT,
+ tenant_member_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS 'ODS 原始明细表:助教服务流水。来源:export/test-json-doc/assistant_service_records.json;分析:assistant_service_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '【说明】本条助教流水记录的主键 ID(流水唯一标识)。 【示例】2957913441292165(用于本条助教流水记录的主键 ID(流水唯一标识))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '【说明】门店 ID,本数据中指“朗朗桌球”这一家门店。 【示例】2790685415443269(用于门店 ID,本数据中指“朗朗桌球”这一家门店)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '【说明】门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '【说明】球台 ID。 【示例】2793020259897413(用于球台 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '【说明】订单结算 ID,相当于“结账单号”的内部主键。 【示例】2957913171693253(用于订单结算 ID,相当于“结账单号”的内部主键)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '【说明】订单交易号,整个订单层面的编号。 【示例】2957784612605829(用于订单交易号,整个订单层面的编号)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '【说明】关联到“支付记录”的主键 ID。 【示例】0(用于关联到“支付记录”的主键 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '【说明】订单中“助教项目明细”的内部 ID。 【示例】2957788717240005(用于订单中“助教项目明细”的内部 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_type。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '【说明】助教姓名,如“何海婷”“胡敏”等。 【示例】何海婷(用于助教姓名,如“何海婷”“胡敏”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '【说明】助教编号,例如 "27"。 【示例】27(用于助教编号,例如 "27")。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantNo。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '【说明】助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。 【示例】10(用于助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_level。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.levelname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - levelName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_assistant_id IS '【说明】门店维度的助教 ID。 【示例】2946266869435205(用于门店维度的助教 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_id IS '【说明】助教服务“课程/技能”ID。 【示例】2790683529513797(用于助教服务“课程/技能”ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skillname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skillName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.system_member_id IS '【说明】系统级会员 ID(全集团统一 ID)。 【示例】0(用于系统级会员 ID(全集团统一 ID))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - system_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tablename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tableName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_member_id IS '【说明】商户维度会员 ID(门店/品牌内的会员主键)。 【示例】0(用于商户维度会员 ID(门店/品牌内的会员主键))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.user_id IS '【说明】助教对应的“用户账号 ID”(系统级用户)。 【示例】2946266868976453(用于助教对应的“用户账号 ID”(系统级用户))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '【说明】助教对外昵称,如“佳怡”“周周”“球球”等。 【示例】泡芙(用于助教对外昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】27-泡芙(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '【说明】助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。 【示例】NULL(用于助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '【说明】按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。 【示例】206.67(用于按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '【说明】台账记录的计时总秒数。 【示例】7592(用于台账记录的计时总秒数)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_count。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '【说明】助教服务 标准单价(通常是标价:每小时、每节课的单价)。 【示例】98.0(用于助教服务 标准单价(通常是标价:每小时、每节课的单价))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '【说明】台账层面记录的开始时间。 【示例】2025-11-09 21:18:18(用于台账层面记录的开始时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '【说明】台账层面的结束时间。 【示例】2025-11-09 23:24:50(用于台账层面的结束时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '【说明】收银员手动给予的减免金额(人工改价)。 【示例】0.0(用于收银员手动给予的减免金额(人工改价))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - manual_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '【说明】由会员卡折扣产生的优惠金额。 【示例】0.0(用于由会员卡折扣产生的优惠金额)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '【说明】由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。 【示例】0.0(用于由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '【说明】用于记录与助教结算的金额(平台预留的“成本/分成”字段)。 【示例】0.0(用于记录与助教结算的金额(平台预留的“成本/分成”字段))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '【说明】实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。 【示例】168.0(用于实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - projected_income。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '【说明】实际使用时长(秒)。 【示例】7592(用于实际使用时长(秒))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - real_use_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '【说明】计费秒数 / 应计收入对应的时间。 【示例】7560(用于计费秒数 / 应计收入对应的时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - income_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '【说明】助教实际开始服务时间。 【示例】2025-11-09 21:18:18(用于助教实际开始服务时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - start_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '【说明】最后一次使用(实际服务)时间。 【示例】2025-11-09 23:24:50(用于最后一次使用(实际服务)时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - last_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '【说明】这条助教流水记录创建时间(一般接近结算/下单时间)。 【示例】2025-11-09 23:25:11(用于这条助教流水记录创建时间(一般接近结算/下单时间))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_single_order。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_trash。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '【说明】废除原因(文本说明),例如“顾客取消”“录入错误”等。 【示例】NULL(用于废除原因(文本说明),例如“顾客取消”“录入错误”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_reason。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '【说明】提出废除申请的员工 ID(通常是操作员/管理员)。 【示例】0(用于提出废除申请的员工 ID(通常是操作员/管理员))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '【说明】废除申请人姓名。 【示例】NULL(用于废除申请人姓名)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '【说明】操作员 ID(录入/结算这条助教服务的员工)。 【示例】2790687322443013(用于操作员 ID(录入/结算这条助教服务的员工))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - operator_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '【说明】操作员姓名,与 operator_id 一起使用,便于直接阅读。 【示例】收银员:郑丽珊(用于操作员姓名,与 operator_id 一起使用,便于直接阅读)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - operator_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '【说明】关联的“营业员/销售员姓名”,用于提成归属。 【示例】NULL(关联的“营业员/销售员姓名”,用于提成归属)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '【说明】营业员用户 ID。 【示例】0(用于营业员用户 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '【说明】助教所属“人事组织/部门 ID”。 【示例】2946266869336901(用于助教所属“人事组织/部门 ID”)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '【说明】加钟秒数,即在原有预约/服务基础上临时追加的时长。 【示例】0(用于加钟秒数,即在原有预约/服务基础上临时追加的时长)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - add_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '【说明】退钟秒数(取消加钟或提前结束退回的时间)。 【示例】0(用于退钟秒数(取消加钟或提前结束退回的时间))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - returns_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '【说明】综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。 【示例】0.0(用于综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '【说明】助教服务所在的球台名称(如 "A17"、"S1")。 【示例】0001-01-01 00:00:00(用于助教服务所在的球台名称(如 "A17"、"S1"))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '【说明】顾客对“技能表现”的评分(整数或打分等级)。 【示例】0(用于顾客对“技能表现”的评分(整数或打分等级))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '【说明】顾客对“服务态度”的评分。 【示例】0(用于顾客对“服务态度”的评分)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '【说明】累计评分总和(可能用于计算平均分),当前为 0。 【示例】0.0(累计评分总和(可能用于计算平均分),当前为 0)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '【说明】1 = 未评价/正常。 【示例】1(用于1 = 未评价/正常)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - grade_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '【说明】该条记录对应的评价次数(或该助教被评价次数快照)。 【示例】0(用于该条记录对应的评价次数(或该助教被评价次数快照))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_not_responding。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_confirm。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - $。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_service_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_service_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS 'ODS 原始明细表:门店桌台主数据。来源:export/test-json-doc/site_tables_master.json;分析:site_tables_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '【说明】台桌主键 ID。 【示例】2791964216463493(用于台桌主键 ID)。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_tables_master.json - data.siteTables - site_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '【说明】门店名称快照,冗余字段,配合 site_id 使用。 【示例】朗朗桌球(用于门店名称快照,冗余字段,配合 site_id 使用)。 【JSON字段】site_tables_master.json - data.siteTables - siteName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '【说明】区域名称,用于前台展示和区域维度管理。 【示例】A区(区域名称,用于前台展示和区域维度管理)。 【JSON字段】site_tables_master.json - data.siteTables - areaName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '【说明】当前值:全部为 2。 【示例】2(用于当前值:全部为 2)。 【JSON字段】site_tables_master.json - data.siteTables - audit_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - charge_free。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '【说明】台桌配置的创建时间或最近一次创建/复制时间。 【示例】2025-07-15 17:52:54(用于台桌配置的创建时间或最近一次创建/复制时间)。 【JSON字段】site_tables_master.json - data.siteTables - create_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '【说明】台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。 【示例】0(台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯)。 【JSON字段】site_tables_master.json - data.siteTables - delay_lights_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】site_tables_master.json - data.siteTables - is_online_reservation。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - is_rest_area。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】site_tables_master.json - data.siteTables - light_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '【说明】小程序二维码 URL。 【示例】2(用于小程序二维码 URL)。 【JSON字段】site_tables_master.json - data.siteTables - only_allow_groupon。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '【说明】订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。 【示例】0(用于订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费))。 【JSON字段】site_tables_master.json - data.siteTables - order_delay_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '【说明】当前值:全部为 1。 【示例】1(用于当前值:全部为 1)。 【JSON字段】site_tables_master.json - data.siteTables - self_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】site_tables_master.json - data.siteTables - show_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '【说明】门店维度的“台桌区域 ID”。 【示例】2791963794329671(用于门店维度的“台桌区域 ID”)。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '【说明】table_status 的中文名称,仅为展示用途。 【示例】空闲中(用于table_status 的中文名称,仅为展示用途)。 【JSON字段】site_tables_master.json - data.siteTables - tableStatusName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '【说明】台呢使用周期阈值,例如达到某个秒数后提醒更换。 【示例】0(用于台呢使用周期阈值,例如达到某个秒数后提醒更换)。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_Cycle。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】1863727(时间字段,用于记录业务时间点/发生时间。)。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '【说明】台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。 【示例】A1(台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段)。 【JSON字段】site_tables_master.json - data.siteTables - table_name。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '【说明】设计上应为“台的基础单价”字段(例如按小时或按局单价)。 【示例】0.0(用于设计上应为“台的基础单价”字段(例如按小时或按局单价))。 【JSON字段】site_tables_master.json - data.siteTables - table_price。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '【说明】台当前运行状态,真实反映某一时刻台的占用/暂停情况。 【示例】1(用于台当前运行状态,真实反映某一时刻台的占用/暂停情况)。 【JSON字段】site_tables_master.json - data.siteTables - table_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '【说明】临时点灯时长(秒),例如手动临时开灯一段时间。 【示例】0(用于临时点灯时长(秒),例如手动临时开灯一段时间)。 【JSON字段】site_tables_master.json - data.siteTables - temporary_light_second。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - virtual_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】site_tables_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/site_tables_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】site_tables_master.json - data.siteTables - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS 'ODS 原始明细表:台费折扣记录。来源:export/test-json-doc/table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '【说明】台费打折 / 调整流水主键 ID。 【示例】2957913441881989(用于台费打折 / 调整流水主键 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '【说明】门店 ID,本批数据全部为同一家门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本批数据全部为同一家门店(朗朗桌球))。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '【说明】门店信息快照,用于报表时直接读取,无需再联门店档案。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(门店信息快照,用于报表时直接读取,无需再联门店档案)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '【说明】台桌 ID。 【示例】2793020259897413(用于台桌 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '【说明】折扣发生时,对应台桌的配置信息快照。 【示例】{"id": 2793020259897413, "tenant_id": 2790683160709957, "tenant_name": "", "siteName": "", "table_name": "S1", "site_ta…(用于折扣发生时,对应台桌的配置信息快照)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tableProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '【说明】租户维度的“台桌区域 ID”。 【示例】2791961347968901(用于租户维度的“台桌区域 ID”)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '【说明】文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。 【示例】1(用于文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - adjust_type。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】148.15(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '【说明】这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。 【示例】1(用于这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '【说明】设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。 【示例】NULL(设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '【说明】打折/调账申请人 ID。 【示例】2790687322443013(用于打折/调账申请人 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '【说明】申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。 【示例】收银员:郑丽珊(用于申请人姓名(带角色描述),为 applicant_id 的冗余显示字段)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '【说明】实际执行调账操作的操作员 ID。 【示例】2790687322443013(用于实际执行调账操作的操作员 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '【说明】操作员姓名。 【示例】收银员:郑丽珊(用于操作员姓名)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '【说明】结算单/小票 ID。 【示例】2957913171693253(用于结算单/小票 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '【说明】订单交易号。 【示例】2957784612605829(用于订单交易号)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '【说明】台费调整记录的创建时间,即打折操作被执行的时间戳。 【示例】2025-11-09 23:25:11(用于台费调整记录的创建时间,即打折操作被执行的时间戳)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_discount_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_discount_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS 'ODS 原始明细表:台费流水。来源:export/test-json-doc/table_fee_transactions.json;分析:table_fee_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '【说明】台费流水记录主键(事实表主键)。 【示例】2957924029058885(用于台费流水记录主键(事实表主键))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '【说明】门店 ID,本次数据全部来自同一门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本次数据全部来自同一门店(朗朗桌球))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '【说明】门店内“台桌区域” ID(站在门店物理布局的角度)。 【示例】2791963794329671(用于门店内“台桌区域” ID(站在门店物理布局的角度))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '【说明】台桌区域的名称,用于门店表现和区域统计。 【示例】A区(台桌区域的名称,用于门店表现和区域统计)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '【说明】租户维度的台桌区域 ID(品牌层面的同一类区域)。 【示例】2791960001957765(用于租户维度的台桌区域 ID(品牌层面的同一类区域))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '【说明】订单交易号,是整笔订单的主编号。 【示例】2957858167230149(用于订单交易号,是整笔订单的主编号)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '【说明】订单支付记录 ID。 【示例】0(用于订单支付记录 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '【说明】结算单号/结账 ID,对应一次结账操作。 【示例】2957922914357125(用于结算单号/结账 ID,对应一次结账操作)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '【说明】台号名称,实际展示给员工/顾客看的桌台编号。 【示例】A17(用于台号名称,实际展示给员工/顾客看的桌台编号)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '【说明】按单价与计费时长计算出的原始应收台费金额。 【示例】48.0(用于按单价与计费时长计算出的原始应收台费金额)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '【说明】台账记录的计费秒数,计费用秒数(应收时长)。 【示例】3600(用于台账记录的计费秒数,计费用秒数(应收时长))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '【说明】台费结算时设置的 每小时单价/计费单价。 【示例】48.0(用于台费结算时设置的 每小时单价/计费单价)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '【说明】台账上的计费起始时间。 【示例】2025-11-09 22:28:57(用于台账上的计费起始时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '【说明】台账上的计费结束时间。 【示例】2025-11-09 23:28:57(用于台账上的计费结束时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '【说明】台开始使用的时间(实际开台时间)。 【示例】2025-11-09 22:28:57(用于台开始使用的时间(实际开台时间))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - start_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '【说明】最后使用/操作时间。 【示例】2025-11-09 23:28:57(用于最后使用/操作时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - last_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '【说明】实际使用的总秒数(系统真实统计的使用时长)。 【示例】3600(用于实际使用的总秒数(系统真实统计的使用时长))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_use_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '【说明】台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。 【示例】0.0(用于台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_charge_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '【说明】加钟秒数,在原有使用基础上追加的时长。 【示例】0(用于加钟秒数,在原有使用基础上追加的时长)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - add_clock_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '【说明】调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。 【示例】0.0(调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - adjust_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '【说明】由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。 【示例】48.0(用于由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - coupon_promotion_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '【说明】由会员权益产生的优惠金额,例如会员折扣、会员价等。 【示例】0.0(用于由会员权益产生的优惠金额,例如会员折扣、会员价等)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '【说明】由储值卡、次卡等“卡内余额”抵扣的金额。 【示例】0.0(用于由储值卡、次卡等“卡内余额”抵扣的金额)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - used_card_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '【说明】管理费字段,用于未来支持“台费附加管理费/服务费”的功能。 【示例】0.0(管理费字段,用于未来支持“台费附加管理费/服务费”的功能)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - mgmt_fee。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '【说明】门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。 【示例】0.0(门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - service_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '【说明】各种附加费用(如管理费、服务费)合计值。 【示例】0.0(用于各种附加费用(如管理费、服务费)合计值)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - fee_total。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '【说明】门店/租户内的会员 ID。 【示例】0(用于门店/租户内的会员 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '【说明】操作员 ID,负责开台/结账的员工账号 ID。 【示例】2790687322443013(用于操作员 ID,负责开台/结账的员工账号 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '【说明】操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。 【示例】收银员:郑丽珊(用于操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '【说明】业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。 【示例】NULL(用于业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '【说明】营业员所属机构/部门 ID。 【示例】0(用于营业员所属机构/部门 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '【说明】营业员的用户 ID(与 salesman_name 搭配)。 【示例】0(用于营业员的用户 ID(与 salesman_name 搭配))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '【说明】这条台费流水记录的创建时间,通常接近结账时间。 【示例】2025-11-09 23:35:57(用于这条台费流水记录的创建时间,通常接近结账时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - $。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS 'ODS 原始明细表:商品库存变动流水。来源:export/test-json-doc/goods_stock_movements.json;分析:goods_stock_movements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '【说明】门店某个“商品库存记录”的主键 ID。 【示例】2957911857581957(用于门店某个“商品库存记录”的主键 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteGoodsStockId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - tenantId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '【说明】门店维度的商品 ID。 【示例】2793026183532613(用于门店维度的商品 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '【说明】商品名称。 【示例】阿萨姆(用于商品名称)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsSecondCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '【说明】库存计量单位。 【示例】瓶(用于库存计量单位)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - unit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '【说明】商品单价(单位金额)。 【示例】8.0(用于商品单价(单位金额))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - price。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '【说明】1:89 条。 【示例】1(用于1:89 条)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - stockType。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '【说明】本次库存数量变化值。 【示例】-1(用于本次库存数量变化值)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - changeNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '【说明】变动前(这次出入库之前)的库存数量。 【示例】28(用于变动前(这次出入库之前)的库存数量)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - startNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '【说明】变动后(出入库之后)的库存数量。 【示例】27(用于变动后(出入库之后)的库存数量)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - endNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '【说明】辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。 【示例】0(用于辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - changeNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '【说明】辅助计量单位的起始库存(例如件/箱等第二单位)。 【示例】0(用于辅助计量单位的起始库存(例如件/箱等第二单位))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - startNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '【说明】辅助单位的变动后库存,同样未启用。 【示例】0(用于辅助单位的变动后库存,同样未启用)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - endNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '【说明】备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。 【示例】NULL(备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - remark。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '【说明】执行此次库存变动的操作人。 【示例】收银员:郑丽珊(用于执行此次库存变动的操作人)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - operatorName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '【说明】这条库存变动记录的创建时间,即发生库存变更的时间点。 【示例】2025-11-09 23:23:34(用于这条库存变动记录的创建时间,即发生库存变更的时间点)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - createTime。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_movements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_movements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS 'ODS 原始明细表:商品分类树。来源:export/test-json-doc/stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '【说明】分类节点主键 ID(在商品分类维度中的唯一标识)。 【示例】2790683528350533(用于分类节点主键 ID(在商品分类维度中的唯一标识))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '【说明】分类名称(实际业务分类名称)。 【示例】槟榔(用于分类名称(实际业务分类名称))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - category_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别。)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - alias_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '【说明】父级分类 ID。 【示例】0(用于父级分类 ID)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - pid。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '【说明】业务大类名称。 【示例】槟榔(用于业务大类名称)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - business_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '【说明】业务大类 ID。 【示例】2790683528317766(用于业务大类 ID)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '【说明】是否启用“营业员”或“导购提成”相关的功能开关。 【示例】2(用于是否启用“营业员”或“导购提成”相关的功能开关)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - open_salesman。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '【说明】子分类数组。 【示例】[{"id": 2790683528350534, "tenant_id": 2790683160709957, "category_name": "槟榔", "alias_name": "", "pid": 27906835283505…(用于子分类数组)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - categoryBoxes。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '【说明】分类的排序序号,用于前端展示顺序的控制。 【示例】1(分类的排序序号,用于前端展示顺序的控制)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - sort。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '【说明】本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1。 【示例】1(用于本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】stock_goods_category_tree.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/stock_goods_category_tree.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS 'ODS 原始明细表:商品库存汇总。来源:export/test-json-doc/goods_stock_summary.json;分析:goods_stock_summary-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '【说明】门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识。 【示例】2791953867886725(用于门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识)。 【JSON字段】goods_stock_summary.json - $ - siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '【说明】商品名称,冗余于门店商品档案的 goods_name。 【示例】东方树叶(用于商品名称,冗余于门店商品档案的 goods_name)。 【JSON字段】goods_stock_summary.json - $ - goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '【说明】商品的计量单位(售卖单位)。 【示例】瓶(用于商品的计量单位(售卖单位))。 【JSON字段】goods_stock_summary.json - $ - goodsUnit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '【说明】一级商品分类 ID。 【示例】2790683528350539(用于一级商品分类 ID)。 【JSON字段】goods_stock_summary.json - $ - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '【说明】二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类。 【示例】2790683528350540(用于二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类)。 【JSON字段】goods_stock_summary.json - $ - goodsCategorySecondId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '【说明】一级分类名称,属于冗余字段,用于直接展示。 【示例】酒水(一级分类名称,属于冗余字段,用于直接展示)。 【JSON字段】goods_stock_summary.json - $ - categoryName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '【说明】查询区间 起始时刻 的库存数量(期初库存)。 【示例】165(用于查询区间 起始时刻 的库存数量(期初库存))。 【JSON字段】goods_stock_summary.json - $ - rangeStartStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '【说明】查询区间 结束时刻 的库存数量(期末库存)。 【示例】118(用于查询区间 结束时刻 的库存数量(期末库存))。 【JSON字段】goods_stock_summary.json - $ - rangeEndStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '【说明】查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等。 【示例】450(用于查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等)。 【JSON字段】goods_stock_summary.json - $ - rangeIn。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '【说明】查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售)。 【示例】-497(用于查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售))。 【JSON字段】goods_stock_summary.json - $ - rangeOut。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '【说明】查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等)。 【示例】488(用于查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等))。 【JSON字段】goods_stock_summary.json - $ - rangeSale。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '【说明】查询区间内,该商品销售的 金额小计(按商品维度汇总)。 【示例】3904.0(用于查询区间内,该商品销售的 金额小计(按商品维度汇总))。 【JSON字段】goods_stock_summary.json - $ - rangeSaleMoney。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '【说明】查询区间内的 盘点调整净变动量(盘盈–盘亏)。 【示例】0(用于查询区间内的 盘点调整净变动量(盘盈–盘亏))。 【JSON字段】goods_stock_summary.json - $ - rangeInventory。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '【说明】导出时刻的实时库存数量。 【示例】118(用于导出时刻的实时库存数量)。 【JSON字段】goods_stock_summary.json - $ - currentStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_summary.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_summary.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】goods_stock_summary.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS 'ODS 原始明细表:支付流水。来源:export/test-json-doc/payment_transactions.json;分析:payment_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '【说明】支付流水记录的主键 ID。 【示例】2957924026486597(用于支付流水记录的主键 ID)。 【JSON字段】payment_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '【说明】支付记录所属的门店 ID。 【示例】2790685415443269(用于支付记录所属的门店 ID)。 【JSON字段】payment_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '【说明】门店信息快照,与其他 JSON 中的 siteProfile 结构一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,与其他 JSON 中的 siteProfile 结构一致)。 【JSON字段】payment_transactions.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '【说明】表示“这条支付记录关联的业务类型”。 【示例】2(用于表示“这条支付记录关联的业务类型”)。 【JSON字段】payment_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '【说明】关联业务记录的主键 ID(按 relate_type 不同指向不同表)。 【示例】2957922914357125(用于关联业务记录的主键 ID(按 relate_type 不同指向不同表))。 【JSON字段】payment_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '【说明】本条支付流水的“支付金额”,单位为元。 【示例】10.0(用于本条支付流水的“支付金额”,单位为元)。 【JSON字段】payment_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '【说明】支付状态枚举字段。 【示例】2(用于支付状态枚举字段)。 【JSON字段】payment_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '【说明】实际支付完成时间(支付状态变为成功的时间戳)。 【示例】2025-11-09 23:35:57(用于实际支付完成时间(支付状态变为成功的时间戳))。 【JSON字段】payment_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '【说明】支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳)。 【示例】2025-11-09 23:35:57(用于支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳))。 【JSON字段】payment_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '【说明】支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种。 【示例】4(用于支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种)。 【JSON字段】payment_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '【说明】每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一)。 【示例】0(用于每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一))。 【JSON字段】payment_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】payment_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/payment_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】payment_transactions.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS 'ODS 原始明细表:退款流水。来源:export/test-json-doc/refund_transactions.json;分析:refund_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '【说明】本条 退款流水 的唯一 ID。 【示例】2955202296416389(用于本条 退款流水 的唯一 ID)。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '【说明】租户/品牌 ID,全系统维度标识该商户。 【示例】2790683160709957(用于租户/品牌 ID,全系统维度标识该商户)。 【JSON字段】refund_transactions.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '【说明】租户(商户)名称。 【示例】朗朗桌球(用于租户(商户)名称)。 【JSON字段】refund_transactions.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】refund_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '【说明】门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致)。 【JSON字段】refund_transactions.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '【说明】本退款对应的“业务类型”。 【示例】5(用于本退款对应的“业务类型”)。 【JSON字段】refund_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '【说明】本次退款关联的业务 ID。 【示例】2955078219057349(用于本次退款关联的业务 ID)。 【JSON字段】refund_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】refund_transactions.json - $ - pay_sn。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '【说明】本次退款的 资金变动金额。 【示例】-5000.0(用于本次退款的 资金变动金额)。 【JSON字段】refund_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '【说明】设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用。 【示例】0.0(用于设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用)。 【JSON字段】refund_transactions.json - $ - refund_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '【说明】舍入金额/抹零金额。 【示例】0.0(用于舍入金额/抹零金额)。 【JSON字段】refund_transactions.json - $ - round_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '【说明】退款在支付渠道层面实际发生的时间。 【示例】2025-11-08 01:27:16(用于退款在支付渠道层面实际发生的时间)。 【JSON字段】refund_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '【说明】本条退款流水在系统内创建时间。 【示例】2025-11-08 01:27:16(用于本条退款流水在系统内创建时间)。 【JSON字段】refund_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】4(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - pay_terminal。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '【说明】支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。 【示例】0(用于支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键)。 【JSON字段】refund_transactions.json - $ - pay_config_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '【说明】当前:全部 0。 【示例】0(用于当前:全部 0)。 【JSON字段】refund_transactions.json - $ - online_pay_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '【说明】第三方支付渠道对本次退款收取的手续费。 【示例】0.0(用于第三方支付渠道对本次退款收取的手续费)。 【JSON字段】refund_transactions.json - $ - channel_fee。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '【说明】支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。 【示例】NULL(用于支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等)。 【JSON字段】refund_transactions.json - $ - channel_payer_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '【说明】第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。 【示例】NULL(用于第三方支付平台的交易号(如微信支付单号、支付宝交易号等))。 【JSON字段】refund_transactions.json - $ - channel_pay_no。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '【说明】租户内部的会员 ID(对应会员档案中的某个主键)。 【示例】0(用于租户内部的会员 ID(对应会员档案中的某个主键))。 【JSON字段】refund_transactions.json - $ - member_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '【说明】关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。 【示例】0(用于关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡))。 【JSON字段】refund_transactions.json - $ - member_card_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '【说明】收银点 ID,例如前台 1、前台 2、自助机等。 【示例】0(用于收银点 ID,例如前台 1、前台 2、自助机等)。 【JSON字段】refund_transactions.json - $ - cashier_point_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '【说明】执行该退款操作的操作员 ID。 【示例】0(用于执行该退款操作的操作员 ID)。 【JSON字段】refund_transactions.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '【说明】当前:全部 2。 【示例】2(用于当前:全部 2)。 【JSON字段】refund_transactions.json - $ - action_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '【说明】当前:全部 1。 【示例】1(用于当前:全部 1)。 【JSON字段】refund_transactions.json - $ - check_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】refund_transactions.json - $ - is_revoke。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】refund_transactions.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '【说明】涉及会员储值卡退款时,暂时冻结的余额金额。 【示例】0.0(用于涉及会员储值卡退款时,暂时冻结的余额金额)。 【JSON字段】refund_transactions.json - $ - balance_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '【说明】与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。 【示例】0.0(用于与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关)。 【JSON字段】refund_transactions.json - $ - card_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】refund_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/refund_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】refund_transactions.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS 'ODS 原始明细表:平台券核销/使用记录。来源:export/test-json-doc/platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '【说明】本条平台验券记录在本系统内的主键 ID。 【示例】2957929042218501(用于本条平台验券记录在本系统内的主键 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '【说明】平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID)。 【示例】7570689090418149418(用于平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID))。 【JSON字段】platform_coupon_redemption_records.json - $ - verify_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '【说明】平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID)。 【示例】5008024789379597447(用于平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID))。 【JSON字段】platform_coupon_redemption_records.json - $ - certificate_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '【说明】券码,顾客出示的团购券密码/编号。 【示例】0102701209726(用于券码,顾客出示的团购券密码/编号)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_code。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '【说明】团购券产品名称(即第三方平台上向顾客展示的名称)。 【示例】【全天可用】中八桌球一小时(A区)(用于团购券产品名称(即第三方平台上向顾客展示的名称))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '【说明】券来源渠道(第三方平台渠道编号)。 【示例】1(用于券来源渠道(第三方平台渠道编号))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_channel。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '【说明】团购券类型。 【示例】1(用于团购券类型)。 【JSON字段】platform_coupon_redemption_records.json - $ - groupon_type。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体。)。 【JSON字段】platform_coupon_redemption_records.json - $ - group_package_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '【说明】顾客在第三方平台上实际支付的价格(团购售价)。 【示例】29.9(用于顾客在第三方平台上实际支付的价格(团购售价))。 【JSON字段】platform_coupon_redemption_records.json - $ - sale_price。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '【说明】券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”)。 【示例】48.0(用于券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_money。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '【说明】券附带的“免费时长”字段(例如送多少分钟台费)。 【示例】0(用于券附带的“免费时长”字段(例如送多少分钟台费))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_free_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_cover。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】617547ec-9697-4f58-a700-b30a49e88904||CgYIASAHKAESLgos9ZhHDryhHb0z3RpdBZ0dVoaQbkldBcx/XTXPV8Te+9SEqYOa7aDp8nbKOpsaAA==(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_remark。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '【说明】值 1:198 条。 【示例】1(用于值 1:198 条)。 【JSON字段】platform_coupon_redemption_records.json - $ - use_status。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '【说明】券被核销/使用的业务时间。 【示例】2025-11-09 23:41:04(用于券被核销/使用的业务时间)。 【JSON字段】platform_coupon_redemption_records.json - $ - consume_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '【说明】验券记录在本系统中创建的时间(记录入库时间)。 【示例】2025-11-09 23:41:03(用于验券记录在本系统中创建的时间(记录入库时间))。 【JSON字段】platform_coupon_redemption_records.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '【说明】另一个层次的团购产品 ID。 【示例】1345108507(用于另一个层次的团购产品 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '【说明】渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键。 【示例】1128411555(用于渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键)。 【JSON字段】platform_coupon_redemption_records.json - $ - channel_deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '【说明】门店内部的订单 ID(平台券核销时对应的店内订单)。 【示例】2957929043037702(用于门店内部的订单 ID(平台券核销时对应的店内订单))。 【JSON字段】platform_coupon_redemption_records.json - $ - site_order_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '【说明】使用券的球台 ID。 【示例】2793001904918661(用于使用券的球台 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - table_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '【说明】商户/租户 ID(品牌级别)。 【示例】2790683160709957(用于商户/租户 ID(品牌级别))。 【JSON字段】platform_coupon_redemption_records.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '【说明】操作员 ID(执行验券操作的收银员/员工)。 【示例】2790687322443013(用于操作员 ID(执行验券操作的收银员/员工))。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '【说明】操作员姓名,例如 "收银员:郑丽珊"。 【示例】收银员:郑丽珊(用于操作员姓名,例如 "收银员:郑丽珊")。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '【说明】把平台验券记录挂到本门店的一条订单上。 【示例】0(用于把平台验券记录挂到本门店的一条订单上)。 【JSON字段】platform_coupon_redemption_records.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】platform_coupon_redemption_records.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】platform_coupon_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/platform_coupon_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】platform_coupon_redemption_records.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ out_goods_id TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS 'ODS 原始明细表:租户商品主数据。来源:export/test-json-doc/tenant_goods_master.json;分析:tenant_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '【说明】商品档案主键 ID,唯一标识一条商品。 【示例】2791925230096261(用于商品档案主键 ID,唯一标识一条商品)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '【说明】商品名称(前台展示名称)。 【示例】东方树叶(用于商品名称(前台展示名称))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '【说明】商品条码(EAN 等),目前未维护。 【示例】NULL(用于商品条码(EAN 等),目前未维护)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '【说明】商品一级分类名称(业务可读)。 【示例】饮料(用于商品一级分类名称(业务可读))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - categoryName。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '【说明】计量单位。 【示例】瓶(用于计量单位)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - unit。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '【说明】商品内部编码(自定义货号/系统货号)。 【示例】1(用于商品内部编码(自定义货号/系统货号))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_number。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.out_goods_id IS '【说明】外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等)。 【示例】0(用于外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - out_goods_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '【说明】商品状态(上架/下架等)。 【示例】1(用于商品状态(上架/下架等))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '【说明】销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。 【示例】1(用于销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '【说明】是否允许参与折扣/打折。 【示例】1(用于是否允许参与折扣/打折)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '【说明】是否启用库存管理。 【示例】1(用于是否启用库存管理)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '【说明】是否在当前门店启用/上架。 【示例】false(用于是否在当前门店启用/上架)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - isInSite。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '【说明】成本价格。 【示例】0.0(用于成本价格)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】1(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '【说明】商品标价 / 售价(标准销售单价)。 【示例】8.0(用于商品标价 / 售价(标准销售单价))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - market_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '【说明】该商品允许售卖的最低价格(底价)。 【示例】0.0(用于该商品允许售卖的最低价格(底价))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '【说明】普通销售提成比例或提成金额的配置字段。 【示例】0(用于普通销售提成比例或提成金额的配置字段)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - common_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '【说明】积分销售提成/积分赠送规则相关配置。 【示例】0(用于积分销售提成/积分赠送规则相关配置)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - point_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '【说明】拼音首字母/助记码。 【示例】DFSY,DFSX(用于拼音首字母/助记码)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '【说明】与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。 【示例】["10000028"](用于与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodityCode。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '【说明】商品编码(通常为对外商品编码或条码)。 【示例】10000028(用于商品编码(通常为对外商品编码或条码))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '【说明】商品封面图片 URL 地址。 【示例】https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(用于商品封面图片 URL 地址)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '【说明】供应商 ID,用于关联到供应商档案。 【示例】0(供应商 ID,用于关联到供应商档案)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - supplier_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '【说明】商品备注名/别名,通常用来配置简写或特殊显示名称。 【示例】NULL(用于商品备注名/别名,通常用来配置简写或特殊显示名称)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - remark_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '【说明】商品档案创建时间。 【示例】2025-07-15 17:13:15(用于商品档案创建时间)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - create_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '【说明】商品档案最近一次修改时间。 【示例】2025-10-29 23:51:38(用于商品档案最近一次修改时间)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - update_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - $。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】tenant_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/tenant_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS 'ODS 原始明细表:团购套餐主数据。来源:export/test-json-doc/group_buy_packages.json;分析:group_buy_packages-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '【说明】门店侧套餐 ID,本文件内部的主键。 【示例】2939215004469573(用于门店侧套餐 ID,本文件内部的主键)。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '【说明】“上层套餐 ID” 或“总部/系统级套餐 ID”。 【示例】1814707240811572(用于“上层套餐 ID” 或“总部/系统级套餐 ID”)。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '【说明】团购套餐名称,用于前台展示和核销界面。 【示例】早场特惠一小时(团购套餐名称,用于前台展示和核销界面)。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '【说明】语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。 【示例】0.0(用于语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格))。 【JSON字段】group_buy_packages.json - data.packageCouponList - selling_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '【说明】券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。 【示例】0.0(用于券面值或内部结算面值,表示该套餐在门店侧对应的金额额度)。 【JSON字段】group_buy_packages.json - data.packageCouponList - coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '【说明】预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。 【示例】0(用于预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码))。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_info。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '【说明】套餐开始生效的日期时间。 【示例】2025-10-27 00:00:00(用于套餐开始生效的日期时间)。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '【说明】套餐失效的日期时间(到这个时间点后不可使用)。 【示例】2026-10-28 00:00:00(用于套餐失效的日期时间(到这个时间点后不可使用))。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '【说明】每日可用起始时间点(第一段)。 【示例】00:00:00(用于每日可用起始时间点(第一段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '【说明】每日可用的结束时间点(第一段)。 【示例】1.00:00:00(用于每日可用的结束时间点(第一段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '【说明】附加可用时间段的起始时间(第二段)。 【示例】00:00:00(用于附加可用时间段的起始时间(第二段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '【说明】附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。 【示例】1.00:00:00(用于附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用)。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '【说明】套餐内包含的时长(秒)。 【示例】3600(用于套餐内包含的时长(秒))。 【JSON字段】group_buy_packages.json - data.packageCouponList - duration。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '【说明】可使用次数上限。 【示例】9999999(用于可使用次数上限)。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '【说明】一般用于文字描述可用日期范围(例如“周一至周五”)。 【示例】NULL(一般用于文字描述可用日期范围(例如“周一至周五”))。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_range。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '【说明】原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。 【示例】0(用于原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '【说明】套餐适用的“门店台区名称”,用于显示和筛选。 【示例】A区(套餐适用的“门店台区名称”,用于显示和筛选)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '【说明】用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。 【示例】NULL(用于用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '【说明】与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。 【示例】0(与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择)。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '【说明】实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。 【示例】2791960001957765(用于实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围)。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '【说明】门店名称。 【示例】朗朗桌球(用于门店名称)。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '【说明】原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。 【示例】0(用于原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置)。 【JSON字段】group_buy_packages.json - data.packageCouponList - card_type_ids。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - system_group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '【说明】内部业务子类型,具体含义需要结合系统文档。 【示例】2(用于内部业务子类型,具体含义需要结合系统文档)。 【JSON字段】group_buy_packages.json - data.packageCouponList - type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '【说明】1:13 条。 【示例】1(用于1:13 条)。 【JSON字段】group_buy_packages.json - data.packageCouponList - effective_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '【说明】启用状态。 【示例】1(用于启用状态)。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_enabled。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】group_buy_packages.json - data.packageCouponList - max_selectable_categories。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '【说明】1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。 【示例】1(用于1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等)。 【JSON字段】group_buy_packages.json - data.packageCouponList - area_tag_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '【说明】创建人信息,一般包含“角色:姓名”。 【示例】店长:郑丽珊(用于创建人信息,一般包含“角色:姓名”)。 【JSON字段】group_buy_packages.json - data.packageCouponList - creator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '【说明】该套餐在系统中创建的时间。 【示例】2025-10-27 18:24:09(用于该套餐在系统中创建的时间)。 【JSON字段】group_buy_packages.json - data.packageCouponList - create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_packages.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_packages.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】group_buy_packages.json - data.packageCouponList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS 'ODS 原始明细表:团购核销记录。来源:export/test-json-doc/group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '【说明】本条“团购套餐流水”记录的 主键 ID。 【示例】2957924029615941(用于本条“团购套餐流水”记录的 主键 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '【说明】门店 ID,与其它 JSON 中一致。 【示例】2790685415443269(用于门店 ID,与其它 JSON 中一致)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '【说明】门店名称,冗余展示用。 【示例】朗朗桌球(用于门店名称,冗余展示用)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - siteName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '【说明】本次使用券所关联的 球台名称/台号。 【示例】A17(用于本次使用券所关联的 球台名称/台号)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '【说明】该球台所属的 台区名称。 【示例】A区(用于该球台所属的 台区名称)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableAreaName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '【说明】租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。 【示例】2791960001957765(用于租户级台区分组 ID,表示当前使用券的台桌所属的区域组合)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '【说明】订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。 【示例】2957858167230149(用于订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '【说明】结算单 ID(小票结账主键)。 【示例】2957922914357125(用于结算单 ID(小票结账主键))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '【说明】指向支付记录表中的支付流水 ID。 【示例】0(用于指向支付记录表中的支付流水 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '【说明】订单中“券使用记录”的 ID。 【示例】2957858168229573(用于订单中“券使用记录”的 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_channel。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '【说明】团购券券码,核销时扫描/录入的字符串。 【示例】0107892475999(用于团购券券码,核销时扫描/录入的字符串)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_code。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '【说明】本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。 【示例】48.0(用于本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '【说明】平台/上游系统中的券记录主键 ID,“券来源 ID”。 【示例】2957858168229573(用于平台/上游系统中的券记录主键 ID,“券来源 ID”)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_origin_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '【说明】台费侧关联的“团购项目名称”(记账名)。 【示例】全天A区中八一小时(用于台费侧关联的“团购项目名称”(记账名))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '【说明】团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。 【示例】NULL(用于团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '【说明】本次券实际冲抵台费的金额。 【示例】48.0(用于本次券实际冲抵台费的金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '【说明】按此次优惠实际计算的“核销秒数”。 【示例】3600(用于按此次优惠实际计算的“核销秒数”)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '【说明】对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。 【示例】29.9(用于对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '【说明】流水状态。 【示例】1(用于流水状态)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '【说明】本次结算中该球台总计计费的秒数(整台的台费计费时间)。 【示例】3600(用于本次结算中该球台总计计费的秒数(整台的台费计费时间))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_charge_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '【说明】团购/促销活动 ID。 【示例】2957858166460101(用于团购/促销活动 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_activity_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '【说明】团购套餐定义 ID。 【示例】2798727423528005(用于团购套餐定义 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '【说明】团购套餐定义的“标准时长”(券本身标称的可用时长)。 【示例】3600(用于团购套餐定义的“标准时长”(券本身标称的可用时长))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '【说明】优惠类型。 【示例】1(用于优惠类型)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - offer_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '【说明】分摊到“助教服务”的促销金额。 【示例】0.0(用于分摊到“助教服务”的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '【说明】进一步细分助教服务的促销金额。 【示例】0.0(用于进一步细分助教服务的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '【说明】本次券使用中,分摊到“台费服务费”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“台费服务费”部分的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '【说明】本次券使用中,分摊到“商品”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“商品”部分的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goods_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '【说明】来自“充值类优惠”的分摊金额(例如储值赠送部分)。 【示例】0.0(用于来自“充值类优惠”的分摊金额(例如储值赠送部分))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - recharge_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '【说明】本次促销中,属于“奖励金/积分抵扣”的金额。 【示例】0.0(用于本次促销中,属于“奖励金/积分抵扣”的金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - reward_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '【说明】商品规格价格,用于商品类促销分摊时使用。 【示例】0.0(商品规格价格,用于商品类促销分摊时使用)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goodsOptionPrice。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '【说明】营业员姓名。 【示例】NULL(用于营业员姓名)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '【说明】营业员所属组织 ID。 【示例】0(用于营业员所属组织 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '【说明】营业员角色 ID。 【示例】0(用于营业员角色 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '【说明】营业员/业务员用户 ID。 【示例】0(用于营业员/业务员用户 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '【说明】执行本次核销/结算操作的 操作员 ID。 【示例】2790687322443013(用于执行本次核销/结算操作的 操作员 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '【说明】操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。 【示例】收银员:郑丽珊(用于操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '【说明】是否单独作为一条订单行。 【示例】1(用于是否单独作为一条订单行)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '【说明】本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。 【示例】2025-11-09 23:35:57(用于本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - $。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS 'ODS 原始明细表:结算小票明细。来源:export/test-json-doc/settlement_ticket_details.json;分析:settlement_ticket_details-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '【说明】结算单 ID(和顶层字段相同,再次冗余)。 【示例】2957922914357125(用于结算单 ID(和顶层字段相同,再次冗余))。 【JSON字段】settlement_ticket_details.json - $ - orderSettleId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '【说明】本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。 【示例】NULL(用于本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等))。 【JSON字段】settlement_ticket_details.json - $ - actualPayment。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '【说明】人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计。 【示例】NULL(用于人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计)。 【JSON字段】settlement_ticket_details.json - $ - adjustAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '【说明】针对“助教项目”的人工减免金额汇总(整单维度)。 【示例】NULL(用于针对“助教项目”的人工减免金额汇总(整单维度))。 【JSON字段】settlement_ticket_details.json - $ - assistantManualDiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '【说明】本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。 【示例】NULL(用于本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额))。 【JSON字段】settlement_ticket_details.json - $ - balanceAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '【说明】本单结算操作员名称(带角色前缀文字)。 【示例】NULL(用于本单结算操作员名称(带角色前缀文字))。 【JSON字段】settlement_ticket_details.json - $ - cashierName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '【说明】本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。 【示例】NULL(用于本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠))。 【JSON字段】settlement_ticket_details.json - $ - consumeMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '【说明】本单由优惠券抵扣的金额汇总。 【示例】NULL(用于本单由优惠券抵扣的金额汇总)。 【JSON字段】settlement_ticket_details.json - $ - couponAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '【说明】配送地址(若存在外送业务时使用)。 【示例】NULL(用于配送地址(若存在外送业务时使用))。 【JSON字段】settlement_ticket_details.json - $ - deliveryAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '【说明】配送费金额(如果支持外送业务)。 【示例】NULL(用于配送费金额(如果支持外送业务))。 【JSON字段】settlement_ticket_details.json - $ - deliveryFee。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '【说明】商品小计金额(通常 = 单价 × 数量,未考虑其他折扣)。 【示例】NULL(用于商品小计金额(通常 = 单价 × 数量,未考虑其他折扣))。 【JSON字段】settlement_ticket_details.json - $ - ledgerAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '【说明】会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。 【示例】NULL(用于会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用)。 【JSON字段】settlement_ticket_details.json - $ - memberDeductAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '【说明】由“会员权益/折扣”产生的优惠金额总计(整单维度)。 【示例】NULL(用于由“会员权益/折扣”产生的优惠金额总计(整单维度))。 【JSON字段】settlement_ticket_details.json - $ - memberOfferAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '【说明】本单通过线上支付渠道退回的金额(如微信/支付宝退款)。 【示例】NULL(用于本单通过线上支付渠道退回的金额(如微信/支付宝退款))。 【JSON字段】settlement_ticket_details.json - $ - onlineReturnAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '【说明】订单备注,由收银员录入,用于记录与本单相关的特殊说明。 【示例】NULL(订单备注,由收银员录入,用于记录与本单相关的特殊说明)。 【JSON字段】settlement_ticket_details.json - $ - orderRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '【说明】结算单编号(与 ID 独立的一套编号体系,如流水号)。 【示例】NULL(用于结算单编号(与 ID 独立的一套编号体系,如流水号))。 【JSON字段】settlement_ticket_details.json - $ - orderSettleNumber。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '【说明】使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。 【示例】NULL(使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用)。 【JSON字段】settlement_ticket_details.json - $ - payMemberBalance。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '【说明】本单最终支付成功时间。 【示例】NULL(用于本单最终支付成功时间)。 【JSON字段】settlement_ticket_details.json - $ - payTime。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '【说明】结算主支付方式编码(汇总视角)。 【示例】NULL(用于结算主支付方式编码(汇总视角))。 【JSON字段】settlement_ticket_details.json - $ - paymentMethod。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '【说明】积分抵扣对应的成本金额(成本侧)。 【示例】NULL(用于积分抵扣对应的成本金额(成本侧))。 【JSON字段】settlement_ticket_details.json - $ - pointDiscountCost。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '【说明】积分抵扣对应的金额(售价侧)。 【示例】NULL(用于积分抵扣对应的金额(售价侧))。 【JSON字段】settlement_ticket_details.json - $ - pointDiscountPrice。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '【说明】预付金/定金在本单中使用的金额。 【示例】NULL(用于预付金/定金在本单中使用的金额)。 【JSON字段】settlement_ticket_details.json - $ - prepayMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '【说明】本单涉及的退款金额(汇总)。 【示例】NULL(用于本单涉及的退款金额(汇总))。 【JSON字段】settlement_ticket_details.json - $ - refundAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '【说明】本单涉及的退货金额汇总。 【示例】NULL(用于本单涉及的退货金额汇总)。 【JSON字段】settlement_ticket_details.json - $ - returnGoodsAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '【说明】用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。 【示例】NULL(用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示)。 【JSON字段】settlement_ticket_details.json - $ - rewardName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '【说明】结算类型字符串标识。 【示例】NULL(用于结算类型字符串标识)。 【JSON字段】settlement_ticket_details.json - $ - settleType。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '【说明】门店地址(详细地址)。 【示例】NULL(用于门店地址(详细地址))。 【JSON字段】settlement_ticket_details.json - $ - siteAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '【说明】门店电话。 【示例】NULL(用于门店电话)。 【JSON字段】settlement_ticket_details.json - $ - siteBusinessTel。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】settlement_ticket_details.json - $ - siteId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '【说明】门店名称,如“朗朗桌球”。 【示例】NULL(用于门店名称,如“朗朗桌球”)。 【JSON字段】settlement_ticket_details.json - $ - siteName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '【说明】租户 / 商户 ID(品牌维度)。 【示例】NULL(用于租户 / 商户 ID(品牌维度))。 【JSON字段】settlement_ticket_details.json - $ - tenantId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '【说明】租户名称,如“朗朗桌球”。 【示例】NULL(用于租户名称,如“朗朗桌球”)。 【JSON字段】settlement_ticket_details.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '【说明】自定义小票内容,如商家自定义宣传语、条款等。 【示例】NULL(用于自定义小票内容,如商家自定义宣传语、条款等)。 【JSON字段】settlement_ticket_details.json - $ - ticketCustomContent。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '【说明】小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。 【示例】NULL(小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示))。 【JSON字段】settlement_ticket_details.json - $ - ticketRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '【说明】代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。 【示例】NULL(代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录))。 【JSON字段】settlement_ticket_details.json - $ - voucherMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '【说明】不是会员卡主键,而是本次结账时的会员信息快照。 【示例】NULL(用于不是会员卡主键,而是本次结账时的会员信息快照)。 【JSON字段】settlement_ticket_details.json - $ - memberProfile。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '【说明】本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。 【示例】NULL(用于本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构)。 【JSON字段】settlement_ticket_details.json - $ - orderItem。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_ticket_details.json - $ - tenantMemberCardLogs。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】settlement_ticket_details.json - $ - $。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_ticket_details.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_ticket_details.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ batch_stock_quantity NUMERIC(18,2),
+ days_available INT,
+ provisional_total_cost NUMERIC(18,2),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ sort INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS 'ODS 原始明细表:门店商品主数据。来源:export/test-json-doc/store_goods_master.json;分析:store_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '【说明】门店商品 ID,门店维度的商品主键。 【示例】2793025851560005(用于门店商品 ID,门店维度的商品主键)。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '【说明】门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。 【示例】朗朗桌球(用于门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案)。 【JSON字段】store_goods_master.json - data.orderGoodsList - siteName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '【说明】租户/品牌维度的商品 ID,相当于“全局商品 ID”。 【示例】2792178593255301(用于租户/品牌维度的商品 ID,相当于“全局商品 ID”)。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '【说明】商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。 【示例】合味道泡面(用于商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '【说明】商品条形码(如 EAN-13 编码),用于扫码销售。 【示例】NULL(商品条形码(如 EAN-13 编码),用于扫码销售)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2791941988405125(用于商品一级分类 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2793236829620037(用于商品二级分类 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '【说明】一级分类名称,如“零食”“酒水”“服务费”等。 【示例】零食(用于一级分类名称,如“零食”“酒水”“服务费”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - oneCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '【说明】二级分类名称,如“面”“洋酒”“纸巾”等。 【示例】面(用于二级分类名称,如“面”“洋酒”“纸巾”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - twoCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '【说明】商品计量单位(销售单位)。 【示例】桶(用于商品计量单位(销售单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - unit。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '【说明】商品标准销售价(挂牌价),单位为元。 【示例】12.0(用于商品标准销售价(挂牌价),单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '【说明】商品成本价(单件成本)。 【示例】0.0(用于商品成本价(单件成本))。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '【说明】1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。 【示例】1(用于1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算)。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '【说明】最低允许成交价(限价)。 【示例】7.0(用于最低允许成交价(限价))。 【JSON字段】store_goods_master.json - data.orderGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '【说明】安全库存量(阈值),低于该值时系统可以提示补货。 【示例】0(用于安全库存量(阈值),低于该值时系统可以提示补货)。 【JSON字段】store_goods_master.json - data.orderGoodsList - safe_stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '【说明】当前可用库存数量(以 unit 为单位)。 【示例】18(用于当前可用库存数量(以 unit 为单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '【说明】副单位库存数量。 【示例】0(用于副单位库存数量)。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock_A。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '【说明】在当前统计口径下的销售数量(总销量,单位同 unit)。 【示例】104(用于在当前统计口径下的销售数量(总销量,单位同 unit))。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_num。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '【说明】总采购成本,单位为元。 【示例】0.0(用于总采购成本,单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '【说明】累计销售数量。 【示例】104(用于累计销售数量)。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '【说明】平均月销量(件/月),根据某个统计周期内的销售数据折算而来。 【示例】1.32(用于平均月销量(件/月),根据某个统计周期内的销售数据折算而来)。 【JSON字段】store_goods_master.json - data.orderGoodsList - average_monthly_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.batch_stock_quantity IS '【说明】当前“批次”的库存数量(主单位)。 【示例】43(用于当前“批次”的库存数量(主单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - batch_stock_quantity。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.days_available IS '【说明】商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间。 【示例】13(用于商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间)。 【JSON字段】store_goods_master.json - data.orderGoodsList - days_available。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.provisional_total_cost IS '【说明】暂估总成本,单位为元。 【示例】0.0(用于暂估总成本,单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - provisional_total_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '【说明】控制商品档案是否参与任何业务(库存、销售等)。 【示例】1(用于控制商品档案是否参与任何业务(库存、销售等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - enable_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '【说明】观察值:全部为 2。 【示例】2(用于观察值:全部为 2)。 【JSON字段】store_goods_master.json - data.orderGoodsList - audit_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '【说明】是否纳入库存管理。 【示例】1(用于是否纳入库存管理)。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '【说明】是否允许参与折扣。 【示例】1(用于是否允许参与折扣)。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '【说明】表示是否允许跨门店调拨或跨站点共享库存。 【示例】2(用于表示是否允许跨门店调拨或跨站点共享库存)。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】store_goods_master.json - data.orderGoodsList - forbid_sell_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】store_goods_master.json - data.orderGoodsList - send_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '【说明】自定义标签类型。 【示例】2(用于自定义标签类型)。 【JSON字段】store_goods_master.json - data.orderGoodsList - custom_label_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '【说明】是否需要在销售时选择规格/选项。 【示例】1(用于是否需要在销售时选择规格/选项)。 【JSON字段】store_goods_master.json - data.orderGoodsList - option_required。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '【说明】销售渠道类型。 【示例】1(用于销售渠道类型)。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sort IS '【说明】排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前)。 【示例】100(排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前))。 【JSON字段】store_goods_master.json - data.orderGoodsList - sort。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '【说明】商品备注(可以写口味说明、供应商、注意事项等)。 【示例】NULL(用于商品备注(可以写口味说明、供应商、注意事项等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '【说明】商品名称的拼音首字母缩写,有时多个别名用逗号分隔。 【示例】HWDPM,GWDPM(用于商品名称的拼音首字母缩写,有时多个别名用逗号分隔)。 【JSON字段】store_goods_master.json - data.orderGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '【说明】商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。 【示例】https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '【说明】门店商品档案创建时间(商品在门店建立档案的时间点)。 【示例】2025-07-16 11:52:51(用于门店商品档案创建时间(商品在门店建立档案的时间点))。 【JSON字段】store_goods_master.json - data.orderGoodsList - create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '【说明】最后一次修改该商品档案的时间(包括价格调整、状态变更等)。 【示例】2025-11-09 07:23:47(用于最后一次修改该商品档案的时间(包括价格调整、状态变更等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - update_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】store_goods_master.json - data.orderGoodsList - $。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ ordergoodsid BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ returns_number INT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS 'ODS 原始明细表:门店商品销售流水。来源:export/test-json-doc/store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '【说明】本条「门店销售流水」记录的主键 ID。 【示例】2957924029550406(用于本条「门店销售流水」记录的主键 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '【说明】门店 ID(系统主键)。 【示例】2790685415443269(用于门店 ID(系统主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - siteName。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '【说明】门店商品 ID。 【示例】2793026176012357(用于门店商品 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '【说明】租户(品牌)级商品 ID(全局商品 ID)。 【示例】2792115932417925(用于租户(品牌)级商品 ID(全局商品 ID))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '【说明】订单结算 ID(结账单主键)。 【示例】2957922914357125(用于订单结算 ID(结账单主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '【说明】订单交易号(业务单号)。 【示例】2957858167230149(用于订单交易号(业务单号))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '【说明】订单商品明细 ID(订单内部的商品行主键)。 【示例】2957858456391557(用于订单商品明细 ID(订单内部的商品行主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ordergoodsid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '【说明】关联支付记录的 ID。 【示例】0(用于关联支付记录的 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '【说明】订单级优惠券 ID。 【示例】0(用于订单级优惠券 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '【说明】销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。 【示例】哇哈哈矿泉水(用于销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '【说明】销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。 【示例】酒水(用于销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '【说明】原始应收金额,公式上接近 ledger_unit_price × ledger_count。 【示例】5.0(用于原始应收金额,公式上接近 ledger_unit_price × ledger_count)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '【说明】销售数量(以 unit 为单位,unit 字段在门店商品档案中)。 【示例】1(用于销售数量(以 unit 为单位,unit 字段在门店商品档案中))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_count。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '【说明】商品在该次销售中的「结算单价」(元/单位)。 【示例】5.0(用于商品在该次销售中的「结算单价」(元/单位))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '【说明】销售流水状态。 【示例】1(用于销售流水状态)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '【说明】本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。 【示例】0.0(用于本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_price IS '【说明】折后单价(元/单位)。 【示例】5.0(用于折后单价(元/单位))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '【说明】被优惠券 / 团购券直接抵扣到这条商品明细上的金额。 【示例】0.0(用于被优惠券 / 团购券直接抵扣到这条商品明细上的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '【说明】由会员身份(会员折扣)针对这一行商品产生的优惠金额。 【示例】0.0(用于由会员身份(会员折扣)针对这一行商品产生的优惠金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '【说明】由优惠券抵扣“选项价格”的金额。 【示例】0.0(用于由优惠券抵扣“选项价格”的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '【说明】由会员折扣作用在“选项价格”上的优惠金额。 【示例】0.0(用于由会员折扣作用在“选项价格”上的优惠金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_member_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '【说明】由积分抵扣的金额(顾客兑换积分抵现金额)。 【示例】0.0(用于由积分抵扣的金额(顾客兑换积分抵现金额))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '【说明】积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。 【示例】0.0(用于积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '【说明】商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。 【示例】5.0(用于商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - real_goods_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '【说明】本条销售对应的成本金额(以元计)。 【示例】0.01(用于本条销售对应的成本金额(以元计))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - cost_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '【说明】本条销售对应的提成金额(给营业员/促销员的提成)。 【示例】0.0(用于本条销售对应的提成金额(给营业员/促销员的提成))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - push_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '【说明】销售类型。 【示例】1(用于销售类型)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '【说明】是否单独订单标识。 【示例】1(用于是否单独订单标识)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_single_order。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '【说明】商品备注/口味说明/特殊说明。 【示例】哇哈哈矿泉水(用于商品备注/口味说明/特殊说明)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - goods_remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '【说明】商品选项(规格/加料)的附加价格。 【示例】0.0(用于商品选项(规格/加料)的附加价格)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '【说明】商品选项名称(如规格、口味:大杯/小杯,不加冰等)。 【示例】NULL(用于商品选项名称(如规格、口味:大杯/小杯,不加冰等))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_value_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '【说明】会员券 ID(比如会员专享优惠券)。 【示例】0(用于会员券 ID(比如会员专享优惠券))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '【说明】套餐券 ID。 【示例】0(用于套餐券 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - package_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '【说明】营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。 【示例】NULL(用于营业员姓名(如果有为具体销售员记业绩,则在此填姓名))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '【说明】营业员的系统角色 ID(例如某个角色代码表示“销售员”)。 【示例】0(用于营业员的系统角色 ID(例如某个角色代码表示“销售员”))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '【说明】营业员用户 ID(系统账号 ID)。 【示例】0(用于营业员用户 ID(系统账号 ID))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '【说明】操作员 ID(录入这笔销售的员工)。 【示例】2790687322443013(用于操作员 ID(录入这笔销售的员工))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '【说明】操作员姓名,文字冗余。 【示例】收银员:郑丽珊(用于操作员姓名,文字冗余)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - openSalesman。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.returns_number IS '【说明】退货数量(如果这条明细做了退货,会记录退货数量)。 【示例】0(用于退货数量(如果这条明细做了退货,会记录退货数量))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - returns_number。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_table_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '【说明】租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。 【示例】2790683528317768(用于租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '【说明】租户级商品一级分类 ID。 【示例】2790683528350540(用于租户级商品一级分类 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '【说明】销售记录创建时间,通常就是结账时间或录入时间。 【示例】2025-11-09 23:35:57(用于销售记录创建时间,通常就是结账时间或录入时间)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - $。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_sales_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_sales_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+
+
diff --git a/etl_billiards/database/schema_dwd_doc.sql b/etl_billiards/database/schema_dwd_doc.sql
index 90f4c82..15bf56c 100644
--- a/etl_billiards/database/schema_dwd_doc.sql
+++ b/etl_billiards/database/schema_dwd_doc.sql
@@ -1,25 +1,112 @@
--- Generated from DWD?????.docx; includes column comments from??
CREATE SCHEMA IF NOT EXISTS billiards_dwd;
SET search_path TO billiards_dwd;
--- dim_site
+CREATE EXTENSION IF NOT EXISTS btree_gist;
+
+DO $$
+DECLARE
+ rec RECORD;
+BEGIN
+ FOR rec IN
+ SELECT table_name
+ FROM information_schema.columns
+ WHERE table_schema = 'billiards_dwd'
+ AND column_name = 'scd2_start_time'
+ LOOP
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_start_time SET DEFAULT now()', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_end_time SET DEFAULT ''9999-12-31''', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_is_current SET DEFAULT 1', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_version SET DEFAULT 1', rec.table_name);
+
+ END LOOP;
+
+ FOR rec IN (
+ SELECT tc.table_name,
+ string_agg(format('%I WITH =', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_eq_expr,
+ string_agg(format('%I', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_cols
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.table_schema = kcu.table_schema
+ AND tc.table_name = kcu.table_name
+ AND tc.constraint_name = kcu.constraint_name
+ WHERE tc.table_schema = 'billiards_dwd'
+ AND tc.constraint_type = 'PRIMARY KEY'
+ AND EXISTS (
+ SELECT 1 FROM information_schema.columns c
+ WHERE c.table_schema = 'billiards_dwd'
+ AND c.table_name = tc.table_name
+ AND c.column_name = 'scd2_start_time'
+ )
+ GROUP BY tc.table_name
+ )
+ LOOP
+ IF NOT EXISTS (
+ SELECT 1 FROM pg_constraint
+ WHERE conname = format('%s_scd2_no_overlap', rec.table_name)
+ AND conrelid = format('billiards_dwd.%s', rec.table_name)::regclass
+ ) THEN
+ EXECUTE format(
+ 'ALTER TABLE billiards_dwd.%I ADD CONSTRAINT %I EXCLUDE USING gist (%s, tstzrange(scd2_start_time, scd2_end_time) WITH &&) WHERE (scd2_is_current = 1);',
+ rec.table_name,
+ rec.table_name || '_scd2_no_overlap',
+ rec.pk_eq_expr
+ );
+ END IF;
+
+ IF to_regclass(format('billiards_dwd.%s_scd2_current_unique_idx', rec.table_name)) IS NULL THEN
+ EXECUTE format(
+ 'CREATE UNIQUE INDEX %I ON billiards_dwd.%I (%s) WHERE (scd2_is_current = 1);',
+ rec.table_name || '_scd2_current_unique_idx',
+ rec.table_name,
+ rec.pk_cols
+ );
+ END IF;
+ END LOOP;
+END
+$$;
+
+
CREATE TABLE IF NOT EXISTS dim_site (
site_id BIGINT,
org_id BIGINT,
- shop_name TEXT,
- business_tel TEXT,
- full_address TEXT,
tenant_id BIGINT,
+ shop_name TEXT,
+ site_label TEXT,
+ full_address TEXT,
+ address TEXT,
+ longitude NUMERIC(10,6),
+ latitude NUMERIC(10,6),
+ tenant_site_region_id BIGINT,
+ business_tel TEXT,
+ site_type INTEGER,
+ shop_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
PRIMARY KEY (site_id)
);
-COMMENT ON COLUMN dim_site.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
-COMMENT ON COLUMN dim_site.org_id IS '上级组织 ID,用于区域组织划分。 | 来源: siteProfile.org_id | 角色: 外键';
-COMMENT ON COLUMN dim_site.shop_name IS '门店名称,展示用。 | 来源: siteProfile.shop_name';
-COMMENT ON COLUMN dim_site.business_tel IS '门店电话。 | 来源: siteProfile.business_tel';
-COMMENT ON COLUMN dim_site.full_address IS '门店完整地址。 | 来源: siteProfile.full_address';
-COMMENT ON COLUMN dim_site.tenant_id IS '租户 ID。与其它表 tenant_id 对应。 | 来源: siteProfile.tenant_id | 角色: 外键';
--- dim_site_Ex
+COMMENT ON TABLE billiards_dwd.dim_site IS 'DWD 维度表:dim_site。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.org_id IS '【说明】组织/机构 ID,用于组织维度归属。 【示例】2790684179467077(组织/机构 ID,用于组织维度归属)。 【ODS来源】table_fee_transactions - siteProfile.org_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - org_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.tenant_id IS '【说明】租户/品牌 ID,用于商户维度过滤与关联。 【示例】2790683160709957(租户/品牌 ID,用于商户维度过滤与关联)。 【ODS来源】table_fee_transactions - siteProfile.tenant_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.shop_name IS '【说明】门店名称,用于展示与查询。 【示例】朗朗桌球(门店名称,用于展示与查询)。 【ODS来源】table_fee_transactions - siteProfile.shop_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_name。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_label IS '【说明】门店标签(如 A/B 店),用于展示与分组。 【示例】A(门店标签(如 A/B 店),用于展示与分组)。 【ODS来源】table_fee_transactions - siteProfile.site_label。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_label。';
+COMMENT ON COLUMN billiards_dwd.dim_site.full_address IS '【说明】门店详细地址,用于展示与地理信息。 【示例】广东省广州市天河区丽阳街12号(门店详细地址,用于展示与地理信息)。 【ODS来源】table_fee_transactions - siteProfile.full_address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - full_address。';
+COMMENT ON COLUMN billiards_dwd.dim_site.address IS '【说明】门店地址简称/快照,用于展示。 【示例】广东省广州市天河区天园街道朗朗桌球(门店地址简称/快照,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - address。';
+COMMENT ON COLUMN billiards_dwd.dim_site.longitude IS '【说明】经度,用于定位与地图展示。 【示例】113.360321(经度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.longitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - longitude(派生:CAST(longitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site.latitude IS '【说明】纬度,用于定位与地图展示。 【示例】23.133629(纬度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.latitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - latitude(派生:CAST(latitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site.tenant_site_region_id IS '【说明】租户下门店区域 ID,用于区域维度分析。 【示例】156440100(租户下门店区域 ID,用于区域维度分析)。 【ODS来源】table_fee_transactions - siteProfile.tenant_site_region_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_site_region_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.business_tel IS '【说明】门店电话,用于联系信息展示。 【示例】13316068642(门店电话,用于联系信息展示)。 【ODS来源】table_fee_transactions - siteProfile.business_tel。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - business_tel。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_type IS '【说明】门店类型枚举,用于门店分类。 【示例】1(门店类型枚举,用于门店分类)。 【ODS来源】table_fee_transactions - siteProfile.site_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site.shop_status IS '【说明】门店状态枚举,用于营业状态标识。 【示例】1(门店状态枚举,用于营业状态标识)。 【ODS来源】table_fee_transactions - siteProfile.shop_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_site_Ex (
site_id BIGINT,
avatar TEXT,
@@ -42,52 +129,70 @@ CREATE TABLE IF NOT EXISTS dim_site_Ex (
shop_status INTEGER,
create_time TIMESTAMPTZ,
update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
PRIMARY KEY (site_id)
);
-COMMENT ON COLUMN dim_site_Ex.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
-COMMENT ON COLUMN dim_site_Ex.avatar IS '门店头像 URL。 | 来源: siteProfile.avatar';
-COMMENT ON COLUMN dim_site_Ex.address IS '地址简写。 | 来源: siteProfile.address';
-COMMENT ON COLUMN dim_site_Ex.longitude IS '经度。 | 来源: siteProfile.longitude';
-COMMENT ON COLUMN dim_site_Ex.latitude IS '纬度。 | 来源: siteProfile.latitude';
-COMMENT ON COLUMN dim_site_Ex.tenant_site_region_id IS '地区编码。 | 来源: siteProfile.tenant_site_region_id';
-COMMENT ON COLUMN dim_site_Ex.auto_light IS '是否自动控制灯光:1=是,2=否(根据系统约定)。 | 来源: siteProfile.auto_light';
-COMMENT ON COLUMN dim_site_Ex.light_status IS '灯光状态,系统预留字段。 | 来源: siteProfile.light_status';
-COMMENT ON COLUMN dim_site_Ex.light_type IS '灯光类型,预留字段。 | 来源: siteProfile.light_type';
-COMMENT ON COLUMN dim_site_Ex.light_token IS '灯光控制令牌。 | 来源: siteProfile.light_token';
-COMMENT ON COLUMN dim_site_Ex.site_type IS '门店类型枚举(未在导出中说明,视系统配置)。 | 来源: siteProfile.site_type';
-COMMENT ON COLUMN dim_site_Ex.site_label IS '门店标签,展示用。 | 来源: siteProfile.site_label';
-COMMENT ON COLUMN dim_site_Ex.attendance_enabled IS '门店是否启用考勤功能:1=启用,2=不启用。 | 来源: siteProfile.attendance_enabled';
-COMMENT ON COLUMN dim_site_Ex.attendance_distance IS '考勤打卡距离限制(米)。 | 来源: siteProfile.attendance_distance';
-COMMENT ON COLUMN dim_site_Ex.customer_service_qrcode IS '客服二维码 URL。 | 来源: siteProfile.customer_service_qrcode';
-COMMENT ON COLUMN dim_site_Ex.customer_service_wechat IS '客服微信号。 | 来源: siteProfile.customer_service_wechat';
-COMMENT ON COLUMN dim_site_Ex.fixed_pay_qrCode IS '固定收款二维码。 | 来源: siteProfile.fixed_pay_qrCode';
-COMMENT ON COLUMN dim_site_Ex.prod_env IS '环境标记(生产/测试)。 | 来源: siteProfile.prod_env';
-COMMENT ON COLUMN dim_site_Ex.shop_status IS '门店状态,未在文档解释。 | 来源: siteProfile.shop_status';
-COMMENT ON COLUMN dim_site_Ex.create_time IS '门店创建时间。 | 来源: siteProfile.create_time';
-COMMENT ON COLUMN dim_site_Ex.update_time IS '门店最近更新时间。 | 来源: siteProfile.update_time';
--- dim_table
+COMMENT ON TABLE billiards_dwd.dim_site_ex IS 'DWD 维度表(扩展字段表):dim_site_ex。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.avatar IS '【说明】门店头像/图片 URL,用于展示。 【示例】https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg(门店头像/图片 URL,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.avatar。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - avatar。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.address IS '【说明】门店地址简称/快照,用于展示。 【示例】广东省广州市天河区天园街道朗朗桌球(门店地址简称/快照,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - address。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.longitude IS '【说明】经度,用于定位与地图展示。 【示例】113.360321(经度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.longitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - longitude(派生:CAST(longitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.latitude IS '【说明】纬度,用于定位与地图展示。 【示例】23.133629(纬度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.latitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - latitude(派生:CAST(latitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.tenant_site_region_id IS '【说明】租户下门店区域 ID,用于区域维度分析。 【示例】156440100(租户下门店区域 ID,用于区域维度分析)。 【ODS来源】table_fee_transactions - siteProfile.tenant_site_region_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_site_region_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.auto_light IS '【说明】是否启用自动灯控配置,用于门店设备策略。 【示例】1(是否启用自动灯控配置,用于门店设备策略)。 【ODS来源】table_fee_transactions - siteProfile.auto_light。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - auto_light。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_status IS '【说明】灯控状态/开关,用于灯控设备管理。 【示例】1(灯控状态/开关,用于灯控设备管理)。 【ODS来源】table_fee_transactions - siteProfile.light_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_type IS '【说明】灯控类型,用于设备类型区分。 【示例】0(灯控类型,用于设备类型区分)。 【ODS来源】table_fee_transactions - siteProfile.light_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_token IS '【说明】灯控控制令牌,用于对接灯控服务。 【示例】NULL(灯控控制令牌,用于对接灯控服务)。 【ODS来源】table_fee_transactions - siteProfile.light_token。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_token。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_type IS '【说明】门店类型枚举,用于门店分类。 【示例】1(门店类型枚举,用于门店分类)。 【ODS来源】table_fee_transactions - siteProfile.site_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_label IS '【说明】门店标签(如 A/B 店),用于展示与分组。 【示例】A(门店标签(如 A/B 店),用于展示与分组)。 【ODS来源】table_fee_transactions - siteProfile.site_label。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_label。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.attendance_enabled IS '【说明】是否启用考勤功能,用于门店考勤配置。 【示例】1(是否启用考勤功能,用于门店考勤配置)。 【ODS来源】table_fee_transactions - siteProfile.attendance_enabled。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - attendance_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.attendance_distance IS '【说明】考勤允许距离(米),用于考勤打卡限制。 【示例】0(考勤允许距离(米),用于考勤打卡限制)。 【ODS来源】table_fee_transactions - siteProfile.attendance_distance。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - attendance_distance。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.customer_service_qrcode IS '【说明】客服二维码 URL,用于引导联系。 【示例】NULL(客服二维码 URL,用于引导联系)。 【ODS来源】table_fee_transactions - siteProfile.customer_service_qrcode。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - customer_service_qrcode。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.customer_service_wechat IS '【说明】客服微信号,用于引导联系。 【示例】NULL(客服微信号,用于引导联系)。 【ODS来源】table_fee_transactions - siteProfile.customer_service_wechat。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - customer_service_wechat。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.fixed_pay_qrcode IS '【说明】固定收款码(二维码)URL,用于收款引导。 【示例】NULL(固定收款码(二维码)URL,用于收款引导)。 【ODS来源】table_fee_transactions - siteProfile.fixed_pay_qrCode。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - fixed_pay_qrCode。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.prod_env IS '【说明】环境标识(生产/测试),用于区分配置环境。 【示例】1(环境标识(生产/测试),用于区分配置环境)。 【ODS来源】table_fee_transactions - siteProfile.prod_env。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - prod_env。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.shop_status IS '【说明】门店状态枚举,用于营业状态标识。 【示例】1(门店状态枚举,用于营业状态标识)。 【ODS来源】table_fee_transactions - siteProfile.shop_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.create_time IS '【说明】门店创建时间(快照字段)。 【示例】NULL(用于门店创建时间(快照字段))。 【ODS来源】table_fee_transactions - siteProfile.create_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - create_time(派生:CAST(create_time AS timestamptz))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.update_time IS '【说明】门店更新时间(快照字段)。 【示例】NULL(用于门店更新时间(快照字段))。 【ODS来源】table_fee_transactions - siteProfile.update_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - update_time(派生:CAST(update_time AS timestamptz))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_table (
table_id BIGINT,
- tenant_id BIGINT,
site_id BIGINT,
table_name TEXT,
site_table_area_id BIGINT,
site_table_area_name TEXT,
tenant_table_area_id BIGINT,
table_price NUMERIC(18,2),
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
PRIMARY KEY (table_id)
);
-COMMENT ON COLUMN dim_table.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_table.tenant_id IS '租户 ID。 | 来源: tenantId | 角色: 外键';
-COMMENT ON COLUMN dim_table.site_id IS '门店 ID。 | 来源: siteId | 角色: 外键';
-COMMENT ON COLUMN dim_table.table_name IS '台桌名称/编号,如 A17、888。 | 来源: tableName';
-COMMENT ON COLUMN dim_table.site_table_area_id IS '门店区 ID,用于区分 A区/B区/补时区等。 | 来源: siteTableAreaId | 角色: 外键';
-COMMENT ON COLUMN dim_table.site_table_area_name IS '区域名称,如 “A区”“补时长”。 | 来源: siteTableAreaName';
-COMMENT ON COLUMN dim_table.tenant_table_area_id IS '租户级区域 ID。 | 来源: tenantTableAreaId | 角色: 外键';
-COMMENT ON COLUMN dim_table.table_price IS '台桌基础单价,从table_fee_transactions取值。方法:对应本表id,table_fee_transactions表的site_table_id。';
--- dim_table_Ex
+COMMENT ON TABLE billiards_dwd.dim_table IS 'DWD 维度表:dim_table。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791964216463493(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - id。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_id。 【JSON字段】site_tables_master.json - data.siteTables - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A1(名称字段,用于展示与辅助识别)。 【ODS来源】site_tables_master - table_name。 【JSON字段】site_tables_master.json - data.siteTables - table_name。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_table_area_id。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】site_tables_master - areaName。 【JSON字段】site_tables_master.json - data.siteTables - areaName。';
+COMMENT ON COLUMN billiards_dwd.dim_table.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_table_area_id。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】site_tables_master - table_price。 【JSON字段】site_tables_master.json - data.siteTables - table_price。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_table_Ex (
table_id BIGINT,
show_status INTEGER,
@@ -95,20 +200,26 @@ CREATE TABLE IF NOT EXISTS dim_table_Ex (
table_cloth_use_time INTEGER,
table_cloth_use_cycle INTEGER,
table_status INTEGER,
- last_maintenance_time TIMESTAMPTZ,
- remark TEXT,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
PRIMARY KEY (table_id)
);
-COMMENT ON COLUMN dim_table_Ex.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_table_Ex.show_status IS '显示状态:1=正常台;其他值=特殊用途(包厢、补时长等)。 | 来源: showStatus';
-COMMENT ON COLUMN dim_table_Ex.is_online_reservation IS '是否可线上预约:1=是,2=否。 | 来源: isOnlineReservation';
-COMMENT ON COLUMN dim_table_Ex.table_cloth_use_time IS '已使用台呢时长(秒)。 | 来源: tableClothUseTime';
-COMMENT ON COLUMN dim_table_Ex.table_cloth_use_cycle IS '台呢更换周期阈值(秒)。 | 来源: tableClothUseCycle';
-COMMENT ON COLUMN dim_table_Ex.table_status IS '当前台桌状态:1=空闲,2=使用中,3=暂停中,4=锁定。 | 来源: tableStatus';
-COMMENT ON COLUMN dim_table_Ex.last_maintenance_time IS '最近保养时间(未在 JSON 中出现)。 | 来源: lastMaintenanceTime';
-COMMENT ON COLUMN dim_table_Ex.remark IS '备注信息。 | 来源: remark';
--- dim_assistant
+COMMENT ON TABLE billiards_dwd.dim_table_ex IS 'DWD 维度表(扩展字段表):dim_table_ex。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791964216463493(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - id。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.show_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】site_tables_master - show_status。 【JSON字段】site_tables_master.json - data.siteTables - show_status。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.is_online_reservation IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】2(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】site_tables_master - is_online_reservation。 【JSON字段】site_tables_master.json - data.siteTables - is_online_reservation。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_cloth_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】1863727(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】site_tables_master - table_cloth_use_time。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_time。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_cloth_use_cycle IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】site_tables_master - table_cloth_use_Cycle。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_Cycle。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】site_tables_master - table_status。 【JSON字段】site_tables_master.json - data.siteTables - table_status。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_assistant (
assistant_id BIGINT,
user_id BIGINT,
@@ -125,25 +236,35 @@ CREATE TABLE IF NOT EXISTS dim_assistant (
resign_time TIMESTAMPTZ,
leave_status INTEGER,
assistant_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (assistant_id)
);
-COMMENT ON COLUMN dim_assistant.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_assistant.user_id IS '系统用户 ID,用于统一跨模块身份。 | 来源: user_id | 角色: 外键';
-COMMENT ON COLUMN dim_assistant.assistant_no IS '助教工号/编号,业务识别用。 | 来源: assistant_no';
-COMMENT ON COLUMN dim_assistant.real_name IS '助教真实姓名。 | 来源: real_name';
-COMMENT ON COLUMN dim_assistant.nickname IS '前台展示昵称。 | 来源: nickname';
-COMMENT ON COLUMN dim_assistant.mobile IS '手机号码。 | 来源: mobile';
-COMMENT ON COLUMN dim_assistant.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_assistant.site_id IS '门店 ID。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dim_assistant.team_id IS '助教团队 ID。 | 来源: team_id | 角色: 外键';
-COMMENT ON COLUMN dim_assistant.team_name IS '团队名称。 | 来源: team_name';
-COMMENT ON COLUMN dim_assistant.level IS '助教等级:8=管理员、10=初级、20=中级、30=高级、40=专家。 | 来源: level';
-COMMENT ON COLUMN dim_assistant.entry_time IS '入职时间。 | 来源: entry_time';
-COMMENT ON COLUMN dim_assistant.resign_time IS '离职时间;远未来日期表示在职。 | 来源: resign_time';
-COMMENT ON COLUMN dim_assistant.leave_status IS '在职状态:0=在职,1=已离职。 | 来源: leave_status';
-COMMENT ON COLUMN dim_assistant.assistant_status IS '账号启用状态:1=启用,2=停用/冻结。 | 来源: assistant_status';
--- dim_assistant_Ex
+COMMENT ON TABLE billiards_dwd.dim_assistant IS 'DWD 维度表:dim_assistant。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271297029(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_no IS '【说明】维度字段,用于补充维度属性。 【示例】31(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - assistant_no。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_no。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.real_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】张静然(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - real_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - real_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】小然(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - nickname。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - nickname。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.mobile IS '【说明】维度字段,用于补充维度属性。 【示例】15119679931(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - mobile。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - tenant_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - site_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.team_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792011585884037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - team_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.team_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】1组(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - team_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.level IS '【说明】维度字段,用于补充维度属性。 【示例】20(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - level。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - level。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.entry_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-02 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - entry_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.resign_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-03 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - resign_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.leave_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - leave_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - leave_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - assistant_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
assistant_id BIGINT,
gender INTEGER,
@@ -189,54 +310,64 @@ CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
light_status INTEGER,
is_team_leader INTEGER,
serial_number BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (assistant_id)
);
-COMMENT ON COLUMN dim_assistant_Ex.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_assistant_Ex.gender IS '性别枚举:0=未填/保密,1=男,2=女。 | 来源: gender';
-COMMENT ON COLUMN dim_assistant_Ex.birth_date IS '出生日期,默认为 0001-01-01 表示未设置。 | 来源: birth_date';
-COMMENT ON COLUMN dim_assistant_Ex.avatar IS '头像 URL。 | 来源: avatar';
-COMMENT ON COLUMN dim_assistant_Ex.introduce IS '个人简介文案(目前为空)。 | 来源: introduce';
-COMMENT ON COLUMN dim_assistant_Ex.video_introduction_url IS '视频介绍 URL。 | 来源: video_introduction_url';
-COMMENT ON COLUMN dim_assistant_Ex.height IS '身高(厘米),0 表示未填。 | 来源: height';
-COMMENT ON COLUMN dim_assistant_Ex.weight IS '体重(公斤),0 表示未填。 | 来源: weight';
-COMMENT ON COLUMN dim_assistant_Ex.shop_name IS '门店名称。 | 来源: shop_name';
-COMMENT ON COLUMN dim_assistant_Ex.group_id IS '上级分组 ID,未使用。 | 来源: group_id';
-COMMENT ON COLUMN dim_assistant_Ex.group_name IS '上级分组名称,空。 | 来源: group_name';
-COMMENT ON COLUMN dim_assistant_Ex.person_org_id IS '人事组织 ID,用于权限和报表分组。 | 来源: person_org_id';
-COMMENT ON COLUMN dim_assistant_Ex.staff_id IS '预留员工 ID(全部为0)。 | 来源: staff_id';
-COMMENT ON COLUMN dim_assistant_Ex.staff_profile_id IS '外部人事档案 ID(全部为0)。 | 来源: staff_profile_id';
-COMMENT ON COLUMN dim_assistant_Ex.assistant_grade IS '平均评分(0 表示暂无)。 | 来源: assistant_grade';
-COMMENT ON COLUMN dim_assistant_Ex.sum_grade IS '总评分累加值。 | 来源: sum_grade';
-COMMENT ON COLUMN dim_assistant_Ex.get_grade_times IS '累计评分次数。 | 来源: get_grade_times';
-COMMENT ON COLUMN dim_assistant_Ex.charge_way IS '计费方式:2=计时,其他未出现。 | 来源: charge_way';
-COMMENT ON COLUMN dim_assistant_Ex.allow_cx IS '是否允许促销计费:1=允许。 | 来源: allow_cx';
-COMMENT ON COLUMN dim_assistant_Ex.is_guaranteed IS '是否有保底:1=是。 | 来源: is_guaranteed';
-COMMENT ON COLUMN dim_assistant_Ex.salary_grant_enabled IS '薪资发放开关(值2,具体含义未知)。 | 来源: salary_grant_enabled';
-COMMENT ON COLUMN dim_assistant_Ex.entry_type IS '入职类型:1=正式;其他未出现。 | 来源: entry_type';
-COMMENT ON COLUMN dim_assistant_Ex.entry_sign_status IS '入职签约状态:0=未签约,1=已签约(未出现)。 | 来源: entry_sign_status';
-COMMENT ON COLUMN dim_assistant_Ex.resign_sign_status IS '离职签约状态,未出现非 0。 | 来源: resign_sign_status';
-COMMENT ON COLUMN dim_assistant_Ex.work_status IS '工作状态:1=在岗,2=离岗。与 leave_status 呼应。 | 来源: work_status';
-COMMENT ON COLUMN dim_assistant_Ex.show_status IS '前台展示状态:1=显示;其他值未出现。 | 来源: show_status';
-COMMENT ON COLUMN dim_assistant_Ex.show_sort IS '前端排序序号。 | 来源: show_sort';
-COMMENT ON COLUMN dim_assistant_Ex.online_status IS '在线状态:1=在线。 | 来源: online_status';
-COMMENT ON COLUMN dim_assistant_Ex.is_delete IS '逻辑删除标记:0=未删除,1=已删除。 | 来源: is_delete';
-COMMENT ON COLUMN dim_assistant_Ex.criticism_status IS '投诉状态:1=正常,2=有投诉。 | 来源: criticism_status';
-COMMENT ON COLUMN dim_assistant_Ex.create_time IS '账号创建时间。 | 来源: create_time';
-COMMENT ON COLUMN dim_assistant_Ex.update_time IS '账号最近修改时间。 | 来源: update_time';
-COMMENT ON COLUMN dim_assistant_Ex.start_time IS '配置生效开始时间。 | 来源: start_time';
-COMMENT ON COLUMN dim_assistant_Ex.end_time IS '配置生效结束时间。 | 来源: end_time';
-COMMENT ON COLUMN dim_assistant_Ex.last_table_id IS '最近服务的台桌 ID(未必存在)。 | 来源: last_table_id';
-COMMENT ON COLUMN dim_assistant_Ex.last_table_name IS '最近服务球台名称。 | 来源: last_table_name';
-COMMENT ON COLUMN dim_assistant_Ex.last_update_name IS '最近更新该账号的管理员。 | 来源: last_update_name';
-COMMENT ON COLUMN dim_assistant_Ex.order_trade_no IS '最近关联的订单号(非外键,仅做展示)。 | 来源: order_trade_no';
-COMMENT ON COLUMN dim_assistant_Ex.ding_talk_synced IS '是否同步钉钉:1=已同步。 | 来源: ding_talk_synced';
-COMMENT ON COLUMN dim_assistant_Ex.site_light_cfg_id IS '灯控配置 ID(未启用)。 | 来源: site_light_cfg_id';
-COMMENT ON COLUMN dim_assistant_Ex.light_equipment_id IS '灯控设备 ID(未启用)。 | 来源: light_equipment_id';
-COMMENT ON COLUMN dim_assistant_Ex.light_status IS '灯控状态(值2,具体含义未知)。 | 来源: light_status';
-COMMENT ON COLUMN dim_assistant_Ex.is_team_leader IS '是否团队长:0=否,1=是。 | 来源: is_team_leader';
-COMMENT ON COLUMN dim_assistant_Ex.serial_number IS '来源: serial_number';
--- dim_member
+COMMENT ON TABLE billiards_dwd.dim_assistant_ex IS 'DWD 维度表(扩展字段表):dim_assistant_ex。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271297029(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.gender IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - gender。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - gender。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.birth_date IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - birth_date。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - birth_date。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.avatar IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - avatar。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - avatar。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.introduce IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - introduce。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - introduce。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.video_introduction_url IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/cbb/userVideo/1753096246308/175309624630830.mp4(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - video_introduction_url。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - video_introduction_url。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.height IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - height。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - height。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.weight IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - weight。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - weight。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.shop_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - shop_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - shop_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.group_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - group_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - group_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.person_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271215109(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - person_org_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - person_org_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.staff_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.staff_profile_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_profile_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_profile_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.assistant_grade IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - assistant_grade。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_grade。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.sum_grade IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - sum_grade。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - sum_grade。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.get_grade_times IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - get_grade_times。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - get_grade_times。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.charge_way IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - charge_way。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - charge_way。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.allow_cx IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - allow_cx。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - allow_cx。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_guaranteed IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_guaranteed。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_guaranteed。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.salary_grant_enabled IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - salary_grant_enabled。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - salary_grant_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.entry_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - entry_type。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_type。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.entry_sign_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - entry_sign_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_sign_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.resign_sign_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - resign_sign_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_sign_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.work_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - work_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - work_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.show_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - show_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.show_sort IS '【说明】维度字段,用于补充维度属性。 【示例】31(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - show_sort。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_sort。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.online_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - online_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - online_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_delete。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.criticism_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - criticism_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - criticism_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-02 15:55:26(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - create_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-03 18:32:07(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - update_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-01 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - start_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-12-01 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - end_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - last_table_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】TV(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - last_table_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_update_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】管理员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - last_update_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_update_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.order_trade_no IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - order_trade_no。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.ding_talk_synced IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - ding_talk_synced。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - ding_talk_synced。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.site_light_cfg_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - site_light_cfg_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_light_cfg_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.light_equipment_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - light_equipment_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_equipment_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.light_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - light_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_team_leader IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_team_leader。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_team_leader。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_accounts_master - serial_number。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - serial_number。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_member (
member_id BIGINT,
system_member_id BIGINT,
@@ -248,20 +379,30 @@ CREATE TABLE IF NOT EXISTS dim_member (
member_card_grade_name TEXT,
create_time TIMESTAMPTZ,
update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (member_id)
);
-COMMENT ON COLUMN dim_member.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_member.system_member_id IS '跨租户全局会员 ID。 | 来源: system_member_id | 角色: 外键';
-COMMENT ON COLUMN dim_member.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_member.register_site_id IS '注册门店 ID。 | 来源: register_site_id | 角色: 外键';
-COMMENT ON COLUMN dim_member.mobile IS '会员手机号。 | 来源: mobile';
-COMMENT ON COLUMN dim_member.nickname IS '昵称(未必是真实姓名)。 | 来源: nickname';
-COMMENT ON COLUMN dim_member.member_card_grade_code IS '会员等级代码:1=金卡?2=银卡?3=钻石卡?4=黑卡?(按照 MD 文档枚举)。 | 来源: member_card_grade_code';
-COMMENT ON COLUMN dim_member.member_card_grade_name IS '等级名称,中文描述。 | 来源: member_card_grade_name';
-COMMENT ON COLUMN dim_member.create_time IS '会员档案创建时间。 | 来源: create_time';
-COMMENT ON COLUMN dim_member.update_time IS '最近更新时间。 | 来源: update_time';
--- dim_member_Ex
+COMMENT ON TABLE billiards_dwd.dim_member IS 'DWD 维度表:dim_member。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204540009605(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - system_member_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - tenant_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - register_site_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.mobile IS '【说明】维度字段,用于补充维度属性。 【示例】18620043391(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - mobile。 【JSON字段】member_profiles.json - data.tenantMemberInfos - mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_member.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】胡先生(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - nickname。 【JSON字段】member_profiles.json - data.tenantMemberInfos - nickname。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_card_grade_code IS '【说明】维度字段,用于补充维度属性。 【示例】2790683528022853(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - member_card_grade_code。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_code。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_card_grade_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】储值卡(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - member_card_grade_name。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:29:33(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_profiles - create_time。 【JSON字段】member_profiles.json - data.tenantMemberInfos - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_profiles - update_time。 【JSON字段】member_profiles.json - data.tenantMemberInfos - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_member_Ex (
member_id BIGINT,
referrer_member_id BIGINT,
@@ -270,17 +411,27 @@ CREATE TABLE IF NOT EXISTS dim_member_Ex (
growth_value NUMERIC(18,2),
user_status INTEGER,
status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (member_id)
);
-COMMENT ON COLUMN dim_member_Ex.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_member_Ex.referrer_member_id IS '推荐人会员 ID,营销分析用。 | 来源: referrer_member_id';
-COMMENT ON COLUMN dim_member_Ex.point IS '积分余额(暂未启用)。 | 来源: point';
-COMMENT ON COLUMN dim_member_Ex.register_site_name IS '注册门店名称。 | 来源: site_name';
-COMMENT ON COLUMN dim_member_Ex.growth_value IS '成长值,暂未启用。 | 来源: growth_value';
-COMMENT ON COLUMN dim_member_Ex.user_status IS '会员状态枚举:1=正常,其它值未出现。 | 来源: user_status';
-COMMENT ON COLUMN dim_member_Ex.status IS '帐户状态:1=正常;其它值未出现。 | 来源: status';
--- dim_member_card_account
+COMMENT ON TABLE billiards_dwd.dim_member_ex IS 'DWD 维度表(扩展字段表):dim_member_ex。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.referrer_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - referrer_member_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - referrer_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.point IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - point。 【JSON字段】member_profiles.json - data.tenantMemberInfos - point。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.register_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - site_name。 【JSON字段】member_profiles.json - data.tenantMemberInfos - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.growth_value IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - growth_value。 【JSON字段】member_profiles.json - data.tenantMemberInfos - growth_value。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.user_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_profiles - user_status。 【JSON字段】member_profiles.json - data.tenantMemberInfos - user_status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_profiles - status。 【JSON字段】member_profiles.json - data.tenantMemberInfos - status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_member_card_account (
member_card_id BIGINT,
tenant_id BIGINT,
@@ -299,27 +450,37 @@ CREATE TABLE IF NOT EXISTS dim_member_card_account (
last_consume_time TIMESTAMPTZ,
status INTEGER,
is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (member_card_id)
);
-COMMENT ON COLUMN dim_member_card_account.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_member_card_account.tenant_id IS '租户/品牌 ID,用于分隔不同业务主体。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_member_card_account.register_site_id IS '开卡门店 ID,对应 dim_site.site_id。 | 来源: register_site_id | 角色: 外键';
-COMMENT ON COLUMN dim_member_card_account.tenant_member_id IS '对应会员档案中的 member_id(本租户内)。0 表示未绑定会员。 | 来源: tenant_member_id | 角色: 外键';
-COMMENT ON COLUMN dim_member_card_account.system_member_id IS '全局会员 ID,用于跨租户统一会员身份。0 表示未绑定会员。 | 来源: system_member_id | 角色: 外键';
-COMMENT ON COLUMN dim_member_card_account.card_type_id IS '卡种 ID,指向卡种配置表。与下面的 grade_code 共同定义卡类别。 | 来源: card_type_id | 角色: 外键';
-COMMENT ON COLUMN dim_member_card_account.member_card_grade_code IS '卡等级/卡类代码,区别不同类别卡。2790683528022853=储值卡,2790683528022856=活动抵用券,2790683528022855=台费卡,2790683528022858=酒水卡,2790683528022857=月卡';
-COMMENT ON COLUMN dim_member_card_account.member_card_grade_code_name IS '卡等级中文名称,与 member_card_grade_code 一一对应。 | 来源: member_card_grade_code_name';
-COMMENT ON COLUMN dim_member_card_account.member_card_type_name IS '卡类型名称,通常与 grade_code_name 相同,纯展示字段。 | 来源: member_card_type_name';
-COMMENT ON COLUMN dim_member_card_account.member_name IS '持卡会员姓名快照,部分为空表示未绑定。 | 来源: member_name';
-COMMENT ON COLUMN dim_member_card_account.member_mobile IS '持卡会员手机号快照。 | 来源: member_mobile';
-COMMENT ON COLUMN dim_member_card_account.balance IS '当前余额或额度。对储值卡表示余额,对其他卡表示剩余金额或次数。 | 来源: balance';
-COMMENT ON COLUMN dim_member_card_account.start_time IS '卡片有效期开始时间。 | 来源: start_time';
-COMMENT ON COLUMN dim_member_card_account.end_time IS '卡片有效期结束时间。 | 来源: end_time';
-COMMENT ON COLUMN dim_member_card_account.last_consume_time IS '最近一次消费时间;若为 "1970-01-01" 表示未消费过。 | 来源: last_consume_time';
-COMMENT ON COLUMN dim_member_card_account.status IS '卡状态:1=正常可用;4=过期/停用。其他值在数据中未出现。 | 来源: status';
-COMMENT ON COLUMN dim_member_card_account.is_delete IS '逻辑删除标记:0=未删除;1=已删除。 | 来源: is_delete';
--- dim_member_card_account_Ex
+COMMENT ON TABLE billiards_dwd.dim_member_card_account IS 'DWD 维度表:dim_member_card_account。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955206162843781(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - tenant_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - register_site_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - tenant_member_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204540009605(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - system_member_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.card_type_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793266846533445(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - card_type_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_type_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_grade_code IS '【说明】维度字段,用于补充维度属性。 【示例】2790683528022856(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - member_card_grade_code。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_grade_code_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】活动抵用券(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_card_grade_code_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】活动抵用券(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_card_type_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_type_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】胡先生(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_mobile IS '【说明】维度字段,用于补充维度属性。 【示例】18620043391(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - member_mobile。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.balance IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - balance。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - balance。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:31:12(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - start_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2225-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - end_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.last_consume_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 07:48:23(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - last_consume_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - last_consume_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_stored_value_cards - status。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_stored_value_cards - is_delete。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
member_card_id BIGINT,
site_name TEXT,
@@ -373,62 +534,72 @@ CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
goodsCategoryId TEXT,
pdAssisnatLevel TEXT,
cxAssisnatLevel TEXT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (member_card_id)
);
-COMMENT ON COLUMN dim_member_card_account_Ex.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_member_card_account_Ex.site_name IS '门店名称展示字段(全部相同)。 | 来源: site_name';
-COMMENT ON COLUMN dim_member_card_account_Ex.tenant_name IS '租户名称(当前导出为空)。 | 来源: tenantName';
-COMMENT ON COLUMN dim_member_card_account_Ex.tenantAvatar IS '租户头像 URL(当前导出为空)。 | 来源: tenantAvatar';
-COMMENT ON COLUMN dim_member_card_account_Ex.effect_site_id IS '卡片限定生效门店 ID。0 表示不限门店,配合 able_cross_site=1 表示全店通用。 | 来源: effect_site_id';
-COMMENT ON COLUMN dim_member_card_account_Ex.able_cross_site IS '是否允许跨门店使用该卡:1=允许跨店;0=仅限开卡门店。 | 来源: able_cross_site';
-COMMENT ON COLUMN dim_member_card_account_Ex.card_physics_type IS '物理卡类型:1=实体/标准卡;其他值未出现,含义未知。 | 来源: card_physics_type';
-COMMENT ON COLUMN dim_member_card_account_Ex.card_no IS '物理卡号或条码(当前全部为空)。 | 来源: card_no';
-COMMENT ON COLUMN dim_member_card_account_Ex.bind_password IS '卡绑定密码(未启用)。 | 来源: bind_password';
-COMMENT ON COLUMN dim_member_card_account_Ex.use_scene IS '使用场景说明(当前为空)。 | 来源: use_scene';
-COMMENT ON COLUMN dim_member_card_account_Ex.denomination IS '面额或初始储值额度(当前均为 0.0,未启用)。 | 来源: denomination';
-COMMENT ON COLUMN dim_member_card_account_Ex.create_time IS '卡片创建时间。 | 来源: create_time';
-COMMENT ON COLUMN dim_member_card_account_Ex.disable_start_time IS '卡片禁用开始时间,当前为默认值表示未禁用。 | 来源: disable_start_time';
-COMMENT ON COLUMN dim_member_card_account_Ex.disable_end_time IS '卡片禁用结束时间,当前为默认值表示未禁用。 | 来源: disable_end_time';
-COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_give IS '是否允许转赠给他人:0=不允许;1=允许。 | 来源: is_allow_give';
-COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_order_deduct IS '是否允许在订单层面统一扣款:0=不允许;1=允许。 | 来源: is_allow_order_deduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.sort IS '前端排序序号。 | 来源: sort';
-COMMENT ON COLUMN dim_member_card_account_Ex.table_discount IS '台费折扣率(折扣百分比,10.0=不打折,9.0=九折等)。当前全部 10.0。 | 来源: table_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount IS '商品折扣率,当前为 10.0 表示无折扣。 | 来源: goods_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount IS '助教服务折扣率,当前为 10.0。 | 来源: assistant_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount IS '助教奖励折扣率,当前为 10.0(未启用)。 | 来源: assistant_reward_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.table_service_discount IS '台费服务类折扣率,当前为 10.0。 | 来源: table_service_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_discount IS '商品服务折扣率,当前为 10.0。 | 来源: goods_service_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_discount IS '助教服务类折扣率,当前为 10.0。 | 来源: assistant_service_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.coupon_discount IS '使用券的折扣比例(全部 10.0,未使用)。 | 来源: coupon_discount';
-COMMENT ON COLUMN dim_member_card_account_Ex.table_discount_sub_switch IS '台费折扣叠加开关:1=叠加其他折扣;2=不叠加,仅用卡折扣。 | 来源: table_discount_sub_switch';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_sub_switch IS '商品折扣叠加开关,意义同上。 | 来源: goods_discount_sub_switch';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount_sub_switch IS '助教折扣叠加开关,意义同上。 | 来源: assistant_discount_sub_switch';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount_sub_switch IS '助教奖励折扣叠加开关(未启用)。 | 来源: assistant_reward_discount_sub_switch';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_range_type IS '商品折扣范围类型,未在文档说明具体含义。 | 来源: goods_discount_range_type';
-COMMENT ON COLUMN dim_member_card_account_Ex.table_deduct_radio IS '台费抵扣比例(百分比)。100.0 表示允许全额抵扣;0=不允许。 | 来源: table_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_deduct_radio IS '商品抵扣比例,意义同上。 | 来源: goods_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_deduct_radio IS '助教抵扣比例,意义同上。 | 来源: assistant_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.table_service_deduct_radio IS '台费服务金抵扣比例。 | 来源: table_service_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_deduct_radio IS '商品服务金抵扣比例。 | 来源: goods_service_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_deduct_radio IS '助教服务金抵扣比例。 | 来源: assistant_service_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_deduct_radio IS '助教奖励金抵扣比例(未启用)。 | 来源: assistant_reward_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.coupon_deduct_radio IS '券抵扣比例(未启用)。 | 来源: coupon_deduct_radio';
-COMMENT ON COLUMN dim_member_card_account_Ex.cardSettleDeduct IS '结算时统一扣卡金额配置(当前为 0.0,未使用)。 | 来源: cardSettleDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.tableCardDeduct IS '台费扣卡金额配置,当前 0.0。 | 来源: tableCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.tableServiceCardDeduct IS '台费服务金扣卡金额配置。 | 来源: tableServiceCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.goodsCarDeduct IS '商品扣卡金额配置。 | 来源: goodsCarDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.goodsServiceCardDeduct IS '商品服务金扣卡金额配置。 | 来源: goodsServiceCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistantCardDeduct IS '助教扣卡金额配置。 | 来源: assistantCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistantServiceCardDeduct IS '助教服务金扣卡金额配置。 | 来源: assistantServiceCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.assistantRewardCardDeduct IS '助教奖励金扣卡金额配置(未启用)。 | 来源: assistantRewardCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.couponCardDeduct IS '使用券扣卡金额配置。 | 来源: couponCardDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.deliveryFeeDeduct IS '配送费扣卡金额配置(未启用)。 | 来源: deliveryFeeDeduct';
-COMMENT ON COLUMN dim_member_card_account_Ex.tableAreaId IS '可用台区 ID 列表,空表示不限台区。 | 来源: tableAreaId';
-COMMENT ON COLUMN dim_member_card_account_Ex.goodsCategoryId IS '可用商品分类 ID 列表,空表示不限制商品类别。 | 来源: goodsCategoryId';
-COMMENT ON COLUMN dim_member_card_account_Ex.pdAssisnatLevel IS '允许的陪打助教等级列表,空表示不限。 | 来源: pdAssisnatLevel';
-COMMENT ON COLUMN dim_member_card_account_Ex.cxAssisnatLevel IS '允许的促销助教等级列表,空表示不限。 | 来源: cxAssisnatLevel';
--- dim_tenant_goods
+COMMENT ON TABLE billiards_dwd.dim_member_card_account_ex IS 'DWD 维度表(扩展字段表):dim_member_card_account_ex。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955206162843781(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - site_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tenant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - tenantName。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantName。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tenantavatar IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - tenantAvatar。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantAvatar。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.effect_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - effect_site_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - effect_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.able_cross_site IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - able_cross_site。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_cross_site。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.card_physics_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - card_physics_type。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_physics_type。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.card_no IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - card_no。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_no。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.bind_password IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - bind_password。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - bind_password。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.use_scene IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - use_scene。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - use_scene。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.denomination IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - denomination。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - denomination。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:31:12(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - create_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.disable_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - disable_start_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.disable_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - disable_end_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.is_allow_give IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_stored_value_cards - is_allow_give。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_give。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.is_allow_order_deduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - is_allow_order_deduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_order_deduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.sort IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - sort。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_reward_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - coupon_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_reward_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount_range_type IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount_range_type。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_range_type。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - table_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goods_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - table_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goods_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_reward_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.coupon_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - coupon_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.cardsettlededuct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - cardSettleDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cardSettleDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tablecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - tableCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tableservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - tableServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodscardeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goodsCarDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCarDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodsservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goodsServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantrewardcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantRewardCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantRewardCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.couponcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - couponCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - couponCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.deliveryfeededuct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - deliveryFeeDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - deliveryFeeDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tableareaid IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - tableAreaId。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableAreaId。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodscategoryid IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - goodsCategoryId。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCategoryId。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.pdassisnatlevel IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - pdAssisnatLevel。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - pdAssisnatLevel。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.cxassisnatlevel IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - cxAssisnatLevel。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cxAssisnatLevel。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_tenant_goods (
tenant_goods_id BIGINT,
tenant_id BIGINT,
@@ -444,24 +615,34 @@ CREATE TABLE IF NOT EXISTS dim_tenant_goods (
create_time TIMESTAMPTZ,
update_time TIMESTAMPTZ,
is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (tenant_goods_id)
);
-COMMENT ON COLUMN dim_tenant_goods.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_tenant_goods.tenant_id IS '租户/品牌 ID,用于区分不同商户。当前样本中全表同一值,但模型上应作为维表外键,用于关联租户维度。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_tenant_goods.supplier_id IS '供应商 ID,用于关联供应商档案维度。当前样本全部为 0,说明门店尚未维护供应商信息或导出视图未包含真实供应商关联,但字段含义明确。 | 来源: supplier_id | 角色: 外键';
-COMMENT ON COLUMN dim_tenant_goods.category_name IS '商品一级分类名称(可读名称),例如:零食、饮料、香烟、雪糕、小吃、酒水、面、槟榔等。真实分类关联通过 goods_category_id 与 goods_second_category_id 实现,此字段主要用于展示和直观分析。 | 来源: categoryName';
-COMMENT ON COLUMN dim_tenant_goods.goods_category_id IS '商品一级分类 ID。与分类维表(例如 dim_goods_category)关联,构成商品分类的第一层。一个 goods_category_id 对应一个 category_name。 | 来源: goods_category_id | 角色: 外键';
-COMMENT ON COLUMN dim_tenant_goods.goods_second_category_id IS '商品二级分类 ID。与分类维表的二级节点关联,用于更细粒度的品类统计。取值数目约十四种,每个值属于某个一级分类之下。 | 来源: goods_second_category_id | 角色: 外键';
-COMMENT ON COLUMN dim_tenant_goods.goods_name IS '商品名称(前台展示名),如 “东方树叶”“红烧牛肉面”“百威 235 毫升”等。当前样本中基本唯一。作为用户认知的主显示名称,用于报表、前台展示、小票打印。 | 来源: goods_name';
-COMMENT ON COLUMN dim_tenant_goods.goods_number IS '商品内部编号或自定义货号。当前样本中各记录不重复,如 “1”“2”“10”“11” 等。可用于与其他系统对接或人工查找,有一定对账和排错价值。 | 来源: goods_number';
-COMMENT ON COLUMN dim_tenant_goods.unit IS '商品计量单位,例如:瓶、包、个、份、根、盒、杯、桶、盘、支等。用于解释数量含义,是销售数量与库存数量的度量单位。 | 来源: unit';
-COMMENT ON COLUMN dim_tenant_goods.market_price IS '商品标价或标准销售单价。例如 2、5、6、8、10、12、15、18、20、28 元。POS 默认销售价格,结算时的基础金额字段。 | 来源: market_price';
-COMMENT ON COLUMN dim_tenant_goods.goods_state IS '商品状态枚举。当前样本全部为 1,推测含义为“正常”“已上架”或“有效”。其他值(数据中未出现)通常表示下架、停用或草稿状态。用于控制商品是否可销售。 | 来源: goods_state';
-COMMENT ON COLUMN dim_tenant_goods.create_time IS '商品档案创建时间,格式为 “YYYY-MM-DD HH:MM:SS”。每条记录唯一。用于增量抽取和审计,也可用于分析商品生命周期。 | 来源: create_time';
-COMMENT ON COLUMN dim_tenant_goods.update_time IS '商品档案最近一次修改时间,可为空(表示自创建后未修改)。用于增量同步、变化跟踪和审计分析。 | 来源: update_time';
-COMMENT ON COLUMN dim_tenant_goods.is_delete IS '逻辑删除标志。枚举:0 表示未删除(有效商品);1 表示已逻辑删除(在前台不再展示)。当前样本全部为 0。用于软删除控制和历史数据保留。 | 来源: is_delete';
--- dim_tenant_goods_Ex
+COMMENT ON TABLE billiards_dwd.dim_tenant_goods IS 'DWD 维度表:dim_tenant_goods。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791925230096261(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - tenant_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.supplier_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - supplier_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - supplier_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.category_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】饮料(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - categoryName。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - categoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350539(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - goods_category_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_second_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350540(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - goods_second_category_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】东方树叶(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - goods_name。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】tenant_goods_master - goods_number。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_number。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.unit IS '【说明】维度字段,用于补充维度属性。 【示例】瓶(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - unit。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - unit。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.market_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】8.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - market_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - market_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_state。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-07-15 17:13:15(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】tenant_goods_master - create_time。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-29 23:51:38(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】tenant_goods_master - update_time。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - is_delete。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
tenant_goods_id BIGINT,
remark_name VARCHAR(128),
@@ -481,28 +662,38 @@ CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
common_sale_royalty INTEGER,
point_sale_royalty INTEGER,
out_goods_id BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (tenant_goods_id)
);
-COMMENT ON COLUMN dim_tenant_goods_Ex.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_tenant_goods_Ex.remark_name IS '商品备注名或别名,目前样本中均为空。设计用途为简写名、特殊展示名或内部备注,在当前门店尚未启用。 | 来源: remark_name';
-COMMENT ON COLUMN dim_tenant_goods_Ex.pinyin_initial IS '商品拼音首字母或助记码,用于前台按拼音检索,如 “DFSY,DFSX”“HSNRM,GSNRM”“SP” 等。主要为操作便利,对经营分析影响较小。 | 来源: pinyin_initial';
-COMMENT ON COLUMN dim_tenant_goods_Ex.goods_cover IS '商品封面图片 URL,用于前端展示商品图片。多个商品可能共用同一图片。对经营和结算逻辑无直接影响。 | 来源: goods_cover';
-COMMENT ON COLUMN dim_tenant_goods_Ex.goods_bar_code IS '商品条码(如 EAN 码)。当前样本全部为空。含义明确但尚未使用,未来可用于扫码收银或与第三方商品库对接。 | 来源: goods_bar_code';
-COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code IS '对外商品编码或系列编码,用于与外部系统或其他内部模块对接。例如 “10000”“100000”“10000028”等。一个编码在多条商品上复用,说明它不是主键而是“系列标识”或“外部编码”。具体业务含义依赖上游系统定义。 | 来源: commodity_code';
-COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code_list IS '商品编码列表的序列化形式,对应源 JSON 的数组字段(当前每条记录仅一个元素)。设计上支持 “一个商品多个编码” 场景,目前仅为 commodity_code 的冗余表现形式。 | 来源: commodityCode';
-COMMENT ON COLUMN dim_tenant_goods_Ex.min_discount_price IS '商品可售最低价(底价)。部分记录为 0.00,表示未设置底价或沿用系统默认规则。用于限制打折或手动改价的下限,防止亏损销售。 | 来源: min_discount_price';
-COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price IS '商品成本价,当前大多数为 0.00,仅少数录入 2.0、2.5、3.0 等。用于成本核算与毛利分析。虽当前门店未完整维护,但字段含义清晰,属于成本分析必备结构。 | 来源: cost_price';
-COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price_type IS '成本价格类型枚举,用于标识成本价的来源或计算方式。已知取值:1 和 2。常见推测:1 表示手工录入成本;2 表示按最近进货价或加权平均价生成。具体含义需结合系统枚举字典确认。 | 来源: cost_price_type';
-COMMENT ON COLUMN dim_tenant_goods_Ex.able_discount IS '是否允许该商品参与折扣的标志。已知取值:1。按命名推断枚举约定为:1 表示允许参与打折;0 表示不允许参与打折(当前样本未出现)。配合活动、整单折扣等控制哪些商品可享优惠。 | 来源: able_discount';
-COMMENT ON COLUMN dim_tenant_goods_Ex.sale_channel IS '销售渠道类型枚举。当前样本全部为 1,推测为“线下门店正常销售渠道”。理论上可扩展为不同渠道值,例如外卖、小程序、电商等,用于渠道维度分析。具体枚举说明依赖系统配置。 | 来源: sale_channel';
-COMMENT ON COLUMN dim_tenant_goods_Ex.is_warehousing IS '是否纳入库存管理的标志。已知取值:1,表示纳入库存管理;0 则表示不纳入库存管理(虚拟商品等,当前未出现)。本门店所有商品均启用库存管理。 | 来源: is_warehousing';
-COMMENT ON COLUMN dim_tenant_goods_Ex.is_in_site IS '是否在当前门店启用或上架。当前样本全部为 false。由于该文件是租户级商品档案视图,且 isInSite 全为 false,该字段在本视图的实际含义存在不确定性,可能仅在门店级商品表中才有明确业务意义。 | 来源: isInSite';
-COMMENT ON COLUMN dim_tenant_goods_Ex.able_site_transfer IS '是否允许门店间调拨或门店级操作的枚举。已知取值:2 为绝大多数,0 为少数一条。按命名推测大致含义为:2 表示允许调拨或默认允许;0 表示禁止调拨。实际枚举定义需查阅系统配置,当前无法完全确定具体业务规则。 | 来源: able_site_transfer';
-COMMENT ON COLUMN dim_tenant_goods_Ex.common_sale_royalty IS '普通销售提成或佣金配置字段,单位和含义需结合上游系统(可能为金额或比例)。当前样本全部为 0,说明未启用商品级提成配置。 | 来源: common_sale_royalty';
-COMMENT ON COLUMN dim_tenant_goods_Ex.point_sale_royalty IS '积分销售相关的提成或赠送规则配置字段。当前样本全部为 0,同样未启用该功能。具体数值含义(百分比或固定值)需结合系统定义。 | 来源: point_sale_royalty';
-COMMENT ON COLUMN dim_tenant_goods_Ex.out_goods_id IS '外部系统商品 ID,用于对接第三方平台或统一商品库时作为映射主键。目前样本全部为 0,说明尚未配置外部商品映射,具体对接规则依赖上游系统。 | 来源: out_goods_id';
--- dim_store_goods
+COMMENT ON TABLE billiards_dwd.dim_tenant_goods_ex IS 'DWD 维度表(扩展字段表):dim_tenant_goods_ex。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791925230096261(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.remark_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - remark_name。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - remark_name。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.pinyin_initial IS '【说明】维度字段,用于补充维度属性。 【示例】DFSY,DFSX(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - pinyin_initial。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.goods_cover IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_cover。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.goods_bar_code IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_bar_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.commodity_code IS '【说明】维度字段,用于补充维度属性。 【示例】10000028(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - commodity_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.commodity_code_list IS '【说明】维度字段,用于补充维度属性。 【示例】10000028(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - commodity_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.min_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - min_discount_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.cost_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - cost_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.cost_price_type IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】1(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - cost_price_type。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.able_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】tenant_goods_master - able_discount。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.sale_channel IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - sale_channel。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - is_warehousing。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.is_in_site IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】false(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - isInSite(派生:BOOLEAN(isInSite))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - isInSite(派生:BOOLEAN(isInSite))。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.able_site_transfer IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - able_site_transfer。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.common_sale_royalty IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - common_sale_royalty。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - common_sale_royalty。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.point_sale_royalty IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - point_sale_royalty。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - point_sale_royalty。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.out_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - out_goods_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - out_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_store_goods (
site_goods_id BIGINT,
tenant_id BIGINT,
@@ -524,30 +715,40 @@ CREATE TABLE IF NOT EXISTS dim_store_goods (
enable_status INTEGER,
send_state INTEGER,
is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (site_goods_id)
);
-COMMENT ON COLUMN dim_store_goods.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_store_goods.tenant_id IS '租户/品牌 ID,同一品牌下多个门店共享,用于跨门店汇总分析。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_store_goods.site_id IS '门店 ID,对应门店维度表主键。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dim_store_goods.tenant_goods_id IS '租户级(品牌级)商品 ID,用于关联 dim_tenant_goods,实现跨门店统一商品档案。 | 来源: tenant_goods_id | 角色: 外键';
-COMMENT ON COLUMN dim_store_goods.goods_name IS '商品名称,例如“合味道泡面”“地道肠”“茶位费”。 | 来源: goods_name';
-COMMENT ON COLUMN dim_store_goods.goods_category_id IS '商品一级分类 ID,对应商品分类维表主键,与 category_level1_name 一一对应。 | 来源: goods_category_id | 角色: 外键';
-COMMENT ON COLUMN dim_store_goods.goods_second_category_id IS '商品二级分类 ID,其父分类为 goods_category_id。 | 来源: goods_second_category_id | 角色: 外键';
-COMMENT ON COLUMN dim_store_goods.category_level1_name IS '一级分类名称,如“零食”“酒水”“服务费”,用于报表维度展示。 | 来源: oneCategoryName';
-COMMENT ON COLUMN dim_store_goods.category_level2_name IS '二级分类名称,如“面”“洋酒”“纸巾”,用于更细粒度分类分析。 | 来源: twoCategoryName';
-COMMENT ON COLUMN dim_store_goods.batch_stock_qty IS '当前成本批次的库存数量,用于按 cost_price 估算库存价值。 | 来源: batch_stock_quantity';
-COMMENT ON COLUMN dim_store_goods.sale_qty IS '截至导出时的销售数量(件),当前数据中与 total_sales_qty 相同。 | 来源: sale_num';
-COMMENT ON COLUMN dim_store_goods.total_sales_qty IS '累计销售数量;当前导出周期下与 sale_qty 一致,为历史全量口径。 | 来源: total_sales';
-COMMENT ON COLUMN dim_store_goods.sale_price IS '商品标准销售价(挂牌价),单位为元。实际结算可能有折扣或券抵扣。 | 来源: sale_price';
-COMMENT ON COLUMN dim_store_goods.created_at IS '门店商品档案创建时间(在门店建立该商品档案时的时间点)。 | 来源: create_time';
-COMMENT ON COLUMN dim_store_goods.updated_at IS '最近一次修改商品档案的时间(包括价格调整、状态变更等)。 | 来源: update_time';
-COMMENT ON COLUMN dim_store_goods.avg_monthly_sales IS '平均月销量(件/月),由某个统计周期内销售数据折算而来,用于补货和品类管理分析。 | 来源: average_monthly_sales';
-COMMENT ON COLUMN dim_store_goods.goods_state IS '商品基础状态枚举:1=正常状态(主流值),2=特殊状态(如新建未完全启用或停售但未彻底下架,通常伴随 stock=0、days_on_shelf=0)。 | 来源: goods_state';
-COMMENT ON COLUMN dim_store_goods.enable_status IS '档案启用状态:1=启用;2=停用(推测,样本中未出现);控制商品档案是否参与业务处理。 | 来源: enable_status';
-COMMENT ON COLUMN dim_store_goods.send_state IS '销售端可售状态:1=可销售/可下单;其他值可能代表停售或仅内部使用(当前样本全部为 1)。 | 来源: send_state';
-COMMENT ON COLUMN dim_store_goods.is_delete IS '逻辑删除标志:0=未删除(有效档案);1=已删除(逻辑删除,不再参与业务但保留历史引用)。 | 来源: is_delete';
--- dim_store_goods_Ex
+COMMENT ON TABLE billiards_dwd.dim_store_goods IS 'DWD 维度表:dim_store_goods。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793025851560005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - id。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - tenant_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - site_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792178593255301(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - tenant_goods_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】合味道泡面(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - goods_name。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791941988405125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - goods_category_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_second_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793236829620037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - goods_second_category_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.category_level1_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】零食(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - oneCategoryName。 【JSON字段】store_goods_master.json - data.orderGoodsList - oneCategoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.category_level2_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】面(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - twoCategoryName。 【JSON字段】store_goods_master.json - data.orderGoodsList - twoCategoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.batch_stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】18(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.sale_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】104(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - sale_num。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_num。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.total_sales_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】104(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - total_sales。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_sales。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.sale_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】12.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - sale_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.created_at IS '【说明】维度字段,用于补充维度属性。 【示例】2025-07-16 11:52:51(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - create_time。 【JSON字段】store_goods_master.json - data.orderGoodsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.updated_at IS '【说明】维度字段,用于补充维度属性。 【示例】2025-11-09 07:23:47(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - update_time。 【JSON字段】store_goods_master.json - data.orderGoodsList - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.avg_monthly_sales IS '【说明】维度字段,用于补充维度属性。 【示例】1.32(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - average_monthly_sales。 【JSON字段】store_goods_master.json - data.orderGoodsList - average_monthly_sales。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_state。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.enable_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - enable_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - enable_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.send_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - send_state。 【JSON字段】store_goods_master.json - data.orderGoodsList - send_state。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_master - is_delete。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
site_goods_id BIGINT,
site_name TEXT,
@@ -575,36 +776,46 @@ CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
option_required INTEGER,
remark TEXT,
sort_order INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (site_goods_id)
);
-COMMENT ON COLUMN dim_store_goods_Ex.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_store_goods_Ex.site_name IS '门店名称,例如“朗朗桌球”,是对 site_id 的冗余展示,方便直接阅读。 | 来源: siteName';
-COMMENT ON COLUMN dim_store_goods_Ex.unit IS '销售计量单位,如“包”“瓶”“个”“份”“杯”等。 | 来源: unit';
-COMMENT ON COLUMN dim_store_goods_Ex.goods_barcode IS '商品条形码,用于扫码销售;当前样本多为空。 | 来源: goods_bar_code';
-COMMENT ON COLUMN dim_store_goods_Ex.goods_cover_url IS '商品图片 URL,用于前端展示商品图片。 | 来源: goods_cover';
-COMMENT ON COLUMN dim_store_goods_Ex.pinyin_initial IS '商品名称拼音首字母缩写,有时多个别名用逗号分隔,用于按字母快速检索和排序。 | 来源: pinyin_initial';
-COMMENT ON COLUMN dim_store_goods_Ex.stock_qty IS '当前主单位可用库存数量,以 unit 为单位。 | 来源: stock';
-COMMENT ON COLUMN dim_store_goods_Ex.stock_secondary_qty IS '副单位库存数量;若商品存在双单位(如箱/瓶),用于记录副单位库存;当前门店未启用双单位库存,样本中为 0。 | 来源: stock_A';
-COMMENT ON COLUMN dim_store_goods_Ex.safety_stock_qty IS '安全库存阈值,低于该值时系统可提示补货;当前门店尚未配置,样本中为 0。 | 来源: safe_stock';
-COMMENT ON COLUMN dim_store_goods_Ex.cost_price IS '商品单件成本价,单位元;部分商品为 0,表示未录入或由其它模块结转成本。 | 来源: cost_price';
-COMMENT ON COLUMN dim_store_goods_Ex.cost_price_type IS '成本类型枚举:1=固定成本价(按 cost_price 计),2=动态成本价(按采购单等方式结转,当前多数仍为暂估)。 | 来源: cost_price_type';
-COMMENT ON COLUMN dim_store_goods_Ex.provisional_total_cost IS '当前库存暂估总成本,单位元;通常约等于 batch_stock_qty × cost_price。 | 来源: provisional_total_cost';
-COMMENT ON COLUMN dim_store_goods_Ex.total_purchase_cost IS '当前库存总采购成本,单位元;当前样本中与 provisional_total_cost 相等,为后续精算成本预留。 | 来源: total_purchase_cost';
-COMMENT ON COLUMN dim_store_goods_Ex.min_discount_price IS '最低允许成交价(限价),单位元;收银改价时需保证成交价 ≥ 此值,为 0 时表示未设置限价或由其它规则控制。 | 来源: min_discount_price';
-COMMENT ON COLUMN dim_store_goods_Ex.is_discountable IS '是否允许参与折扣的标志:1=允许参与折扣;0=不参与任何折扣策略。当前样本全部为 1。 | 来源: able_discount';
-COMMENT ON COLUMN dim_store_goods_Ex.days_on_shelf IS '商品在架天数或可售天数,大致等于当前时间减去首次上架时间;0 通常表示刚建档或刚启用。 | 来源: days_available';
-COMMENT ON COLUMN dim_store_goods_Ex.audit_status IS '审核状态枚举:2=审核通过(当前唯一值);其他值可能代表待提交、待审核、审核不通过等。 | 来源: audit_status';
-COMMENT ON COLUMN dim_store_goods_Ex.sale_channel IS '销售渠道枚举:当前样本全部为 1 表示线下门店渠道;其他值可用于区分外卖、线上商城等渠道。 | 来源: sale_channel';
-COMMENT ON COLUMN dim_store_goods_Ex.is_warehousing IS '是否纳入库存管理:1=参与库存管理(有出入库流水);0 或其他值可能表示不计库存(样本中全部为 1)。 | 来源: is_warehousing';
-COMMENT ON COLUMN dim_store_goods_Ex.freeze_status IS '冻结状态:0=未冻结;非 0 可能表示锁定库存或禁止出库,具体业务规则需系统确认。 | 来源: freeze';
-COMMENT ON COLUMN dim_store_goods_Ex.forbid_sell_status IS '禁止销售状态:1=未禁止,允许销售;2=被禁止销售,即使上架也不能卖(含义基于命名和行业惯例推测)。 | 来源: forbid_sell_status';
-COMMENT ON COLUMN dim_store_goods_Ex.able_site_transfer IS '是否允许跨门店调拨或跨站点共享库存:2=不允许跨店调拨(当前主流值);0=未配置(个别记录),含义为是否参与跨店调拨功能。 | 来源: able_site_transfer';
-COMMENT ON COLUMN dim_store_goods_Ex.custom_label_type IS '自定义标签类型(基于字段名和取值推测):2=使用自定义标签;1 可能表示使用系统默认标签。具体影响哪些标签功能需业务确认。 | 来源: custom_label_type';
-COMMENT ON COLUMN dim_store_goods_Ex.option_required IS '是否需要额外选项或规格(基于字段名和取值推测):1=不需要额外选项,按单规格销售;其他值可能表示必须选择配料或口味。当前样本全部为 1。 | 来源: option_required';
-COMMENT ON COLUMN dim_store_goods_Ex.remark IS '商品备注,可填写口味说明、供应商信息、注意事项等;当前样本全部为空。 | 来源: remark';
-COMMENT ON COLUMN dim_store_goods_Ex.sort_order IS '前端展示排序权重,控制商品在列表中的显示顺序,具体规则(数值越大还是越小排前)由业务配置决定。 | 来源: sort';
--- dim_goods_category
+COMMENT ON TABLE billiards_dwd.dim_store_goods_ex IS 'DWD 维度表(扩展字段表):dim_store_goods_ex。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793025851560005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - id。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - siteName。 【JSON字段】store_goods_master.json - data.orderGoodsList - siteName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.unit IS '【说明】维度字段,用于补充维度属性。 【示例】桶(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - unit。 【JSON字段】store_goods_master.json - data.orderGoodsList - unit。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.goods_barcode IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_bar_code。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.goods_cover_url IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_cover。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.pinyin_initial IS '【说明】维度字段,用于补充维度属性。 【示例】HWDPM,GWDPM(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - pinyin_initial。 【JSON字段】store_goods_master.json - data.orderGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】18(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.stock_secondary_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock_A。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock_A。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.safety_stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - safe_stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - safe_stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.cost_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - cost_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.cost_price_type IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】1(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - cost_price_type。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.provisional_total_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - total_purchase_cost。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.total_purchase_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - total_purchase_cost。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.min_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】7.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - min_discount_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.is_discountable IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - able_discount。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.days_on_shelf IS '【说明】维度字段,用于补充维度属性。 【示例】13(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - days_available。 【JSON字段】store_goods_master.json - data.orderGoodsList - days_available。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.audit_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - audit_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - audit_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.sale_channel IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - sale_channel。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_master - is_warehousing。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.freeze_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - freeze。 【JSON字段】store_goods_master.json - data.orderGoodsList - freeze。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.forbid_sell_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - forbid_sell_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - forbid_sell_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.able_site_transfer IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - able_site_transfer。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.custom_label_type IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - custom_label_type。 【JSON字段】store_goods_master.json - data.orderGoodsList - custom_label_type。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.option_required IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - option_required。 【JSON字段】store_goods_master.json - data.orderGoodsList - option_required。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.remark IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - remark。 【JSON字段】store_goods_master.json - data.orderGoodsList - remark。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.sort_order IS '【说明】维度字段,用于补充维度属性。 【示例】100(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - sort。 【JSON字段】store_goods_master.json - data.orderGoodsList - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_goods_category (
category_id BIGINT,
tenant_id BIGINT,
@@ -618,22 +829,32 @@ CREATE TABLE IF NOT EXISTS dim_goods_category (
open_salesman INTEGER,
sort_order INTEGER,
is_warehousing INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (category_id)
);
-COMMENT ON COLUMN dim_goods_category.category_id IS '分类节点主键。来自分类树节点的 id,在整个商品分类维度内唯一。用于在事实表中作为商品分类外键引用。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_goods_category.tenant_id IS '租户 ID(商户/品牌 ID)。当前所有节点取值相同,表示同一个租户下的分类树。事实表可通过该字段与租户维度或门店维度间接关联。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dim_goods_category.category_name IS '分类名称。一级大类示例:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。二级子类示例:槟榔、皮头、球杆、其他、饮料、酒水、茶水、咖啡、加料、洋酒、果盘、面、小吃等。用于前台展示和报表按细分类统计。 | 来源: category_name';
-COMMENT ON COLUMN dim_goods_category.alias_name IS '分类别名。当前样例数据全部为空字符串,预留给业务方做简称或别名展示。对现阶段经营分析无影响。 | 来源: alias_name';
-COMMENT ON COLUMN dim_goods_category.parent_category_id IS '父级分类 ID。根节点取值为 0,表示没有父分类;子节点取值为父分类的 id。与 category_id 共同形成树形层级关系。 | 来源: pid | 角色: 外键';
-COMMENT ON COLUMN dim_goods_category.business_name IS '业务大类名称。将多个细分类归入同一业务线。观测值与一级大类相同:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。子类的 business_name 继承所属根节点的大类名称。用于按业务线汇总库存和销售。 | 来源: business_name';
-COMMENT ON COLUMN dim_goods_category.tenant_goods_business_id IS '业务大类 ID。每个 business_name 对应唯一一个 tenant_goods_business_id,根节点和其下所有子节点共享同一取值。例如“酒水”大类及其子类饮料、茶水、咖啡、加料、洋酒拥有相同的业务 ID。可作为外键连接“业务线维度表”。 | 来源: tenant_goods_business_id | 角色: 外键';
-COMMENT ON COLUMN dim_goods_category.category_level IS '分类层级:1 表示一级大类(pid = 0),2 表示二级子类(pid ≠ 0)。方便在报表中区分大类与子类进行分组和展示层级控制。 | 来源: 由 pid 推导';
-COMMENT ON COLUMN dim_goods_category.is_leaf IS '是否叶子节点:1 表示叶子分类(categoryBoxes 为空列表),0 表示非叶子分类(存在子分类)。当前样例数据中,一级大类是非叶子节点,二级分类是叶子节点。用于树状导航或限制只能在叶子分类建商品。 | 来源: 由 categoryBoxes 推导';
-COMMENT ON COLUMN dim_goods_category.open_salesman IS '营业员开关控制。枚举含义根据业务系统定义,一般设计为:1 表示启用营业员/导购相关功能,2 表示关闭或不启用。当前样例所有分类取值为 2,说明这一套分类在库存模块中统一未启用营业员逻辑。对目前的经营分析影响较小。 | 来源: open_salesman';
-COMMENT ON COLUMN dim_goods_category.sort_order IS '分类排序序号。来自 sort 字段,用于前端展示顺序控制,数值越小越靠前。当前大部分分类为 0,仅少数为 1,说明排序配置较为粗略。对指标统计无实质影响。 | 来源: sort';
-COMMENT ON COLUMN dim_goods_category.is_warehousing IS '是否参与库存管理。枚举:1 表示参与库存管理,0 表示不参与(如服务类商品、手工费用)。当前文件中所有分类取值为 1,表示这一份分类树只包含“走库存”的商品分类。可在库存报表中用作过滤条件。 | 来源: is_warehousing';
--- dim_groupbuy_package
+COMMENT ON TABLE billiards_dwd.dim_goods_category IS 'DWD 维度表:dim_goods_category。ODS 来源表:billiards_ods.stock_goods_category_tree(对应 JSON:stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350533(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - tenant_id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】槟榔(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - category_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - category_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.alias_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - alias_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - alias_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.parent_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - pid。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - pid。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.business_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】槟榔(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - business_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - business_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.tenant_goods_business_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528317766(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - tenant_goods_business_id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_level IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - CASE WHEN pid = 0 THEN 1 ELSE 2 END。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN pid = 0 THEN 1 ELSE 2 END。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.is_leaf IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】stock_goods_category_tree - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.open_salesman IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - open_salesman。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - open_salesman。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.sort_order IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - sort。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】stock_goods_category_tree - is_warehousing。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
groupbuy_package_id BIGINT,
tenant_id BIGINT,
@@ -651,26 +872,36 @@ CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
create_time TIMESTAMPTZ,
tenant_table_area_id_list VARCHAR(512),
card_type_ids VARCHAR(255),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (groupbuy_package_id)
);
-COMMENT ON COLUMN dim_groupbuy_package.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_groupbuy_package.tenant_id IS '租户(品牌/商户)ID。本数据集中全表相同,表示同一品牌。 | 来源: tenant_id | 角色: 外键(指向租户维)';
-COMMENT ON COLUMN dim_groupbuy_package.site_id IS '门店 ID,本表所有记录属于同一门店。与其他 JSON 的 site_id 一致。 | 来源: site_id | 角色: 外键(指向门店维)';
-COMMENT ON COLUMN dim_groupbuy_package.package_name IS '团购套餐名称,用于前台展示及核销界面,例如“早场特惠一小时”“KTV欢唱四小时”等。 | 来源: package_name';
-COMMENT ON COLUMN dim_groupbuy_package.package_template_id IS '上层套餐 ID 或总部/系统级套餐 ID。多个 groupbuy_package_id 可能共享同一个 package_template_id,表示同一业务套餐在不同门店或不同版本下的配置。 | 来源: package_id | 角色: 外键(指向套餐模板维,后续可建)';
-COMMENT ON COLUMN dim_groupbuy_package.selling_price IS '团购售卖价,面向顾客在外部平台的成交价格。当前样本全部为 0,实际平台售价可能在外部系统,不在本地落地。 | 来源: selling_price';
-COMMENT ON COLUMN dim_groupbuy_package.coupon_face_value IS '券面值或内部结算面值。表示此套餐在门店侧可以抵扣的金额,用于验券或套餐流水时记账。例如“早场特惠一小时”可配置为 40.00,“KTV欢唱四小时”可配置为 200.00。当前样本为 0 但字段设计上非常关键。 | 来源: coupon_money';
-COMMENT ON COLUMN dim_groupbuy_package.duration_seconds IS '套餐包含的时长,单位为秒。常见取值:3600 表示 1 小时,7200 表示 2 小时,14400 表示 4 小时。核销时可用于换算可用台费时长。 | 来源: duration';
-COMMENT ON COLUMN dim_groupbuy_package.start_time IS '套餐整体生效开始时间。例如“2025-07-20 00:00:00”。通常从某日零点开始。 | 来源: start_time';
-COMMENT ON COLUMN dim_groupbuy_package.end_time IS '套餐整体生效结束时间。在该时间点之后不可使用。极大日期(如 9999-12-31 23:59:59)可视为长期有效。 | 来源: end_time';
-COMMENT ON COLUMN dim_groupbuy_package.table_area_name IS '套餐适用的门店台区名称,例如“A区中八”“B区中八”“斯诺克”“包厢”“KTV”等。主要用于展示和过滤,配合区域 ID 列实现人类可读的说明。 | 来源: table_area_name';
-COMMENT ON COLUMN dim_groupbuy_package.is_enabled IS '启用状态枚举。1 表示启用或上架;2 表示停用或下架。侧重表示“配置是否上架”,与 effective_status 区分。 | 来源: is_enabled';
-COMMENT ON COLUMN dim_groupbuy_package.is_delete IS '逻辑删除标志。0 表示正常;1 表示逻辑删除(数据仍保留但不再使用)。当前样本全部为 0。 | 来源: is_delete';
-COMMENT ON COLUMN dim_groupbuy_package.create_time IS '套餐配置在系统中的创建时间,用于审计和版本追踪。 | 来源: create_time';
-COMMENT ON COLUMN dim_groupbuy_package.tenant_table_area_id_list IS '租户级台区分组 ID 列表。当前每条记录为一个大整数(例如 2791960001957765)字符串,表示“台区分组”主键。系统通过此分组再关联到具体多个台区。 | 来源: tenant_table_area_id_list | 角色: 外键(指向台区分组维,后续可建)';
-COMMENT ON COLUMN dim_groupbuy_package.card_type_ids IS '允许使用本套餐的会员卡类型 ID 列表。当前样本统一为字符串“0”,表示未限制卡种,任意顾客或任意会员卡都可使用。若未来启用,将以分隔的 ID 列表形式记录限定卡种。 | 来源: card_type_ids | 角色: 外键(潜在指向卡种维)';
--- dim_groupbuy_package_Ex
+COMMENT ON TABLE billiards_dwd.dim_groupbuy_package IS 'DWD 维度表:dim_groupbuy_package。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.groupbuy_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2939215004469573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - id。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - tenant_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - site_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.package_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】早场特惠一小时(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - package_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.package_template_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1814707240811572(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - package_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.selling_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_packages - selling_price。 【JSON字段】group_buy_packages.json - data.packageCouponList - selling_price。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.coupon_face_value IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - coupon_money。 【JSON字段】group_buy_packages.json - data.packageCouponList - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.duration_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_packages - duration。 【JSON字段】group_buy_packages.json - data.packageCouponList - duration。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-27 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - start_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2026-10-28 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - end_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - table_area_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.is_enabled IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_packages - is_enabled。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_packages - is_delete。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-27 18:24:09(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - create_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.tenant_table_area_id_list IS '【说明】维度字段,用于补充维度属性。 【示例】2791960001957765(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - tenant_table_area_id_list。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id_list。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.card_type_ids IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - card_type_ids。 【JSON字段】group_buy_packages.json - data.packageCouponList - card_type_ids。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
groupbuy_package_id BIGINT,
site_name VARCHAR(100),
@@ -692,30 +923,40 @@ CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
effective_status INTEGER,
max_selectable_categories INTEGER,
creator_name VARCHAR(100),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
PRIMARY KEY (groupbuy_package_id)
);
-COMMENT ON COLUMN dim_groupbuy_package_Ex.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.site_name IS '门店名称,当前均为“朗朗桌球”。属于冗余展示字段,可用于报表标题。 | 来源: site_name';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_count IS '可使用次数上限。当前全部为 9999999,用作“无限次使用”的哨兵值。若未来限制次数,只需配置为具体次数。 | 来源: usable_count';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.date_type IS '日期限制类型枚举。当前样本全部为 1。推测常见含义:1 表示“全部日期可用”;其他值可用于区分工作日、周末或指定日期等模式。 | 来源: date_type';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_range IS '日期范围说明的文本,例如“周一至周五”等。当前全部为空字符串,实际规则由 date_type 与时间段字段控制。 | 来源: usable_range';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.date_info IS '更细粒度的日期信息,可能用于存储具体日期列表或节假日规则,形式可能是编码或 JSON 字符串。当前几乎全部为空,仅有极少记录为“0”。 | 来源: date_info';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.start_clock IS '每日可用时间段的起始时间(第一段),字符串格式 HH:MM:SS,例如“10:00:00”“00:00:00”。与 end_clock 组合定义日内时段。 | 来源: start_clock';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.end_clock IS '每日可用时间段的结束时间(第一段),字符串格式 HH:MM:SS。与 start_clock 共同描述第一段可用时段。 | 来源: end_clock';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.add_start_clock IS '附加可用时段的起始时间(第二段),格式 HH:MM:SS。当前样本常见值为“00:00:00”或“10:00:00”。用于配置早场加夜场等双时段场景。 | 来源: add_start_clock';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.add_end_clock IS '附加可用时段的结束时间(第二段)。常见值如“1.00:00:00”“18:00:00”“23:59:00”。其中“1.00:00:00”表示跨至次日零点,用于表示“可用到第二天凌晨”的场景。 | 来源: add_end_clock';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.area_tag_type IS '区域标记类型枚举。当前样本全部为 1。推测 1 表示“按台区标签限制”(如 A 区、B 区、中八、斯诺克、包厢、KTV 等)。其他取值可能对应按具体台桌或其它规则限用。 | 来源: area_tag_type';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id IS '单一台区 ID。当前样本全部为 0。原始设计用于限定只能在一个具体区域使用,但由于已引入多选逻辑,实际使用已迁移到 tenant_table_area_id_list。 | 来源: table_area_id';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.tenant_table_area_id IS '租户级台区 ID,单值版本。当前样本全部为 0。与 table_area_id 类似,已被多选列表字段取代。 | 来源: tenant_table_area_id';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id_list IS '门店级台区 ID 列表。当前样本全部为空字符串。根据命名推测原本用于存储多个 table_area_id,实际实现已转向租户维度列表字段。 | 来源: table_area_id_list';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.group_type IS '团购类型枚举。当前样本全部为 1。推测 1 表示“计时类/台费类套餐”。其他取值可能用于商品类套餐、代金券类等,需结合系统配置进一步确认。 | 来源: group_type';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.system_group_type IS '系统级团购类型枚举。当前样本全部为 1。推测 1 表示“券码类团购”,即通过券码核销。其他取值可能为卡内套餐、内部套餐等,具体含义有待业务确认。 | 来源: system_group_type';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.package_type IS '内部业务子类型枚举。样本中取值有 1 与 2,各占比不同。具体含义不明,可能区分不同产品线或套餐来源,例如“平台合作套餐”与“自定义套餐”等,需要参考业务文档。 | 来源: type';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.effective_status IS '当前有效状态枚举,由系统根据时间及配置动态计算。观测值:1 表示当前有效,可正常核销;3 表示失效或已过期(即使 is_enabled 仍为 1,也不可使用)。可用于分析时过滤失效套餐。 | 来源: effective_status';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.max_selectable_categories IS '最大可选择分类数或子项数,具体含义未在样本和说明中体现,当前值全部为 0。可能用于“组合型套餐”中限制可选项目数量。 | 来源: max_selectable_categories';
-COMMENT ON COLUMN dim_groupbuy_package_Ex.creator_name IS '创建人名称,例如“店长:郑丽珊”。主要用于审计追踪和后台展示。 | 来源: creator_name';
--- dwd_settlement_head
+COMMENT ON TABLE billiards_dwd.dim_groupbuy_package_ex IS 'DWD 维度表(扩展字段表):dim_groupbuy_package_ex。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.groupbuy_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2939215004469573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - id。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - site_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.usable_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】9999999(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_packages - usable_count。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_count。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.date_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - date_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.usable_range IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - usable_range。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_range。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.date_info IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - date_info。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_info。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.start_clock IS '【说明】维度字段,用于补充维度属性。 【示例】00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - start_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.end_clock IS '【说明】维度字段,用于补充维度属性。 【示例】1.00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - end_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.add_start_clock IS '【说明】维度字段,用于补充维度属性。 【示例】00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - add_start_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_start_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.add_end_clock IS '【说明】维度字段,用于补充维度属性。 【示例】1.00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - add_end_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_end_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.area_tag_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - area_tag_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - area_tag_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - table_area_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - tenant_table_area_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.table_area_id_list IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - table_area_id_list。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id_list。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.group_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - group_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - group_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.system_group_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - system_group_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - system_group_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.package_type IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - type。 【JSON字段】group_buy_packages.json - data.packageCouponList - type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.effective_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】group_buy_packages - effective_status。 【JSON字段】group_buy_packages.json - data.packageCouponList - effective_status。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.max_selectable_categories IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - max_selectable_categories。 【JSON字段】group_buy_packages.json - data.packageCouponList - max_selectable_categories。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.creator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】店长:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - creator_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - creator_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
CREATE TABLE IF NOT EXISTS dwd_settlement_head (
order_settle_id BIGINT,
tenant_id BIGINT,
@@ -751,40 +992,42 @@ CREATE TABLE IF NOT EXISTS dwd_settlement_head (
point_amount NUMERIC(18,2),
PRIMARY KEY (order_settle_id)
);
-COMMENT ON COLUMN dwd_settlement_head.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
-COMMENT ON COLUMN dwd_settlement_head.tenant_id IS '租户/商户 ID(品牌维度),与各业务 JSON 中的 tenantId 一致。 | 来源: settleList.tenantId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.site_id IS '门店 ID,用于关联门店维表 dim_site。 | 来源: settleList.siteId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.site_name IS '门店名称快照,冗余展示字段,推荐通过 site_id 关联维表获取标准名称。 | 来源: settleList.siteName';
-COMMENT ON COLUMN dwd_settlement_head.table_id IS '结账关联的桌台 ID,对应台桌维表 dim_site_table 的主键。 | 来源: settleList.tableId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.settle_name IS '结账对象名称,一般为 “区域 + 桌号”,如 “A区 A17”,便于报表展示。 | 来源: settleList.settleName';
-COMMENT ON COLUMN dwd_settlement_head.order_trade_no IS '交易号 / 订单流水号,与台费、助教等明细中的 order_trade_no 一致,用于按“交易维度”串联各业务明细。 | 来源: settleList.settleRelateId';
-COMMENT ON COLUMN dwd_settlement_head.create_time IS '结账创建时间(收银端点击“确认结账”的时间),格式:YYYY-MM-DD HH:MM:SS。 | 来源: settleList.createTime';
-COMMENT ON COLUMN dwd_settlement_head.pay_time IS '实际支付完成时间,通常晚于 create_time,用于资金结算及对账分析。 | 来源: settleList.payTime';
-COMMENT ON COLUMN dwd_settlement_head.settle_type IS '结账类型枚举。样本中主要有:1=正常结账;3=特殊类型结账(如挂账、补单、调整单等,具体需业务确认)。 | 来源: settleList.settleType';
-COMMENT ON COLUMN dwd_settlement_head.revoke_order_id IS '若当前记录属于撤销链路,记录对应的撤销单或原单的结账 ID,形成自关联关系。样本中为 0。 | 来源: settleList.revokeOrderId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.member_id IS '会员主键 ID,一般对应租户维度的会员 ID,用于关联 dim_member。 | 来源: settleList.memberId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.member_name IS '会员姓名快照,冗余展示字段;当前样本多为空,推荐通过关联会员维表获取标准姓名。 | 来源: settleList.memberName';
-COMMENT ON COLUMN dwd_settlement_head.member_phone IS '会员手机号快照,冗余展示字段,通常通过会员维表获取更可靠。 | 来源: settleList.memberPhone';
-COMMENT ON COLUMN dwd_settlement_head.member_card_account_id IS '会员卡账户 ID,对应 dim_member_card_account 主键;当前样本多为 0,但结构上是“结账 → 具体卡账户”的外键。 | 来源: settleList.tenantMemberCardId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head.member_card_type_name IS '会员卡类型名称快照,如“储值卡”“次卡”等,便于前端展示和报表查看。 | 来源: settleList.memberCardTypeName';
-COMMENT ON COLUMN dwd_settlement_head.is_bind_member IS '本单是否绑定会员。0=否(散客);1=是(存在 member_id)。样本中多为 0。 | 来源: settleList.isBindMember';
-COMMENT ON COLUMN dwd_settlement_head.member_discount_amount IS '会员折扣产生的优惠金额(元),例如会员卡折扣减免的台费/商品金额,参与整单优惠拆分。 | 来源: settleList.memberDiscountAmount';
-COMMENT ON COLUMN dwd_settlement_head.consume_money IS '本次结账消费总额(原价小计),约等于台费 + 商品 + 助教 + 服务等项目原价金额之和,未扣除任何优惠。 | 来源: settleList.consumeMoney';
-COMMENT ON COLUMN dwd_settlement_head.table_charge_money IS '本单台费(桌台计费部分)的金额(原价侧)。 | 来源: settleList.tableChargeMoney';
-COMMENT ON COLUMN dwd_settlement_head.goods_money IS '本单商品销售原价金额,对应酒水、小吃等商品类消费。 | 来源: settleList.goodsMoney';
-COMMENT ON COLUMN dwd_settlement_head.real_goods_money IS '商品实际计入金额,通常为 goods_money 扣除部分促销/折扣之后的金额。 | 来源: settleList.realGoodsMoney';
-COMMENT ON COLUMN dwd_settlement_head.assistant_pd_money IS '助教“排钟 / 点钟 / 按时长服务”等项目的应计金额(原价侧),与助教流水中的 ledger_amount 汇总对应。 | 来源: settleList.assistantPdMoney';
-COMMENT ON COLUMN dwd_settlement_head.assistant_cx_money IS '助教“超休”类助教项目金额(原价侧),是对助教收入的补充拆分维度,具体业务定义需结合助教模块确认。 | 来源: settleList.assistantCxMoney';
-COMMENT ON COLUMN dwd_settlement_head.adjust_amount IS '手动减免,人工调价金额汇总(整单减免或特殊价格调整),通常正值表示减免额度。 | 来源: settleList.adjustAmount';
-COMMENT ON COLUMN dwd_settlement_head.pay_amount IS '本单顾客“实付金额”(不含券面值这类虚拟抵扣),等于各支付渠道金额之和减去退款等调整。 | 来源: settleList.payAmount';
-COMMENT ON COLUMN dwd_settlement_head.balance_amount IS '从会员储值余额账户中扣除的金额(储值卡消费部分)。 | 来源: settleList.balanceAmount';
-COMMENT ON COLUMN dwd_settlement_head.recharge_card_amount IS '充值卡支付金额(使用充值类卡片余额支付的金额),与储值/充值型卡资金来源相关。 | 来源: settleList.rechargeCardAmount';
-COMMENT ON COLUMN dwd_settlement_head.gift_card_amount IS '礼品卡或代金卡支付金额。 | 来源: settleList.giftCardAmount';
-COMMENT ON COLUMN dwd_settlement_head.coupon_amount IS '本单由优惠券(团购券、代金券等)实际抵扣的金额。 | 来源: settleList.couponAmount';
-COMMENT ON COLUMN dwd_settlement_head.rounding_amount IS '抹零 / 四舍五入产生的金额差值,例如按角、分抹零。 | 来源: settleList.roundingAmount';
-COMMENT ON COLUMN dwd_settlement_head.point_amount IS '积分相关金额或数量。根据系统配置可能表示“使用积分抵扣的金额”或“本单获得的积分折算金额”,文档未给出唯一定义。 | 来源: settleList.pointAmount';
--- dwd_settlement_head_Ex
+COMMENT ON TABLE billiards_dwd.dwd_settlement_head IS 'DWD 明细事实表:dwd_settlement_head。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - id。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tenantid。 【JSON字段】settlement_records.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - siteid。 【JSON字段】settlement_records.json - $ - siteid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - sitename。 【JSON字段】settlement_records.json - $ - sitename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tableid。 【JSON字段】settlement_records.json - $ - tableid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.settle_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - settlename。 【JSON字段】settlement_records.json - $ - settlename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - settlerelateid。 【JSON字段】settlement_records.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - createtime。 【JSON字段】settlement_records.json - $ - createtime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - paytime。 【JSON字段】settlement_records.json - $ - paytime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.settle_type IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - settletype。 【JSON字段】settlement_records.json - $ - settletype。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.revoke_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - revokeorderid。 【JSON字段】settlement_records.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - memberid。 【JSON字段】settlement_records.json - $ - memberid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - membername。 【JSON字段】settlement_records.json - $ - membername。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_phone IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - memberphone。 【JSON字段】settlement_records.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_card_account_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tenantmembercardid。 【JSON字段】settlement_records.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - membercardtypename。 【JSON字段】settlement_records.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.is_bind_member IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isbindmember。 【JSON字段】settlement_records.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - memberdiscountamount。 【JSON字段】settlement_records.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.consume_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - consumemoney。 【JSON字段】settlement_records.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - tablechargemoney。 【JSON字段】settlement_records.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - goodsmoney。 【JSON字段】settlement_records.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - realgoodsmoney。 【JSON字段】settlement_records.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.assistant_pd_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantpdmoney。 【JSON字段】settlement_records.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.assistant_cx_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantcxmoney。 【JSON字段】settlement_records.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - adjustamount。 【JSON字段】settlement_records.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - payamount。 【JSON字段】settlement_records.json - $ - payamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.balance_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - balanceamount。 【JSON字段】settlement_records.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.recharge_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - rechargecardamount。 【JSON字段】settlement_records.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.gift_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - giftcardamount。 【JSON字段】settlement_records.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.coupon_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - couponamount。 【JSON字段】settlement_records.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.rounding_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - roundingamount。 【JSON字段】settlement_records.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.point_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointamount。 【JSON字段】settlement_records.json - $ - pointamount。';
+
+
CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
order_settle_id BIGINT,
serial_number INTEGER,
@@ -818,38 +1061,40 @@ CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
salesman_user_id BIGINT,
PRIMARY KEY (order_settle_id)
);
-COMMENT ON COLUMN dwd_settlement_head_Ex.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
-COMMENT ON COLUMN dwd_settlement_head_Ex.serial_number IS '结账序列号或打印序号,当前样本全部为 0,具体业务用途未在文档中明确。 | 来源: settleList.serialNumber';
-COMMENT ON COLUMN dwd_settlement_head_Ex.settle_status IS '结账状态枚举。当前样本值均为 2,表示“已结算/已完成”;其他取值及含义未在样本和文档中出现,需后续补充。 | 来源: settleList.settleStatus';
-COMMENT ON COLUMN dwd_settlement_head_Ex.can_be_revoked IS '本单是否仍允许撤销/冲正。0=否;1=是。样本中均为 0。主要用于运维控制,分析价值有限。 | 来源: settleList.canBeRevoked';
-COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_order_name IS '撤销单名称/标识,用于人工识别撤销关系;当前样本为空。 | 来源: settleList.revokeOrderName';
-COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_time IS '撤销时间。无撤销时通常为系统默认值(如 0001-01-01 00:00:00)。 | 来源: settleList.revokeTime';
-COMMENT ON COLUMN dwd_settlement_head_Ex.is_first_order IS '是否首单(新客首单)标记。0=否;1=是。当前样本全部为 0,且文档中说明为“推测用途”,具体业务定义需确认。 | 来源: settleList.isFirst';
-COMMENT ON COLUMN dwd_settlement_head_Ex.service_money IS '其他服务费金额(如包间服务费等),用于与台费、商品、助教金额区分。 | 来源: settleList.serviceMoney';
-COMMENT ON COLUMN dwd_settlement_head_Ex.cash_amount IS '现金支付金额。 | 来源: settleList.cashAmount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.card_amount IS '刷卡类支付金额(如银行卡/信用卡等),具体包含哪些通道需结合支付模块确认。 | 来源: settleList.cardAmount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.online_amount IS '线上支付金额汇总(如微信、支付宝、云闪付等),不区分具体通道。 | 来源: settleList.onlineAmount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.refund_amount IS '本单涉及的退款金额(元)。普通正常结账为 0,退单或部分退款时为正数。 | 来源: settleList.refundAmount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.prepay_money IS '本单使用的预付金/定金金额。 | 来源: settleList.prepayMoney';
-COMMENT ON COLUMN dwd_settlement_head_Ex.payment_method IS '支付方式整体标记(枚举)。当前样本值统一为 0,具体各枚举值对应的支付方式未在文档中说明,需业务确认。 | 来源: settleList.paymentMethod';
-COMMENT ON COLUMN dwd_settlement_head_Ex.coupon_sale_amount IS '优惠券本身的售卖金额/成本金额(例如顾客为购买套餐券支付的金额),当前样本多为 0。 | 来源: settleList.couponSaleAmount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.all_coupon_discount IS '所有券类优惠折扣的汇总金额,用于统计“券优惠总额”。 | 来源: settleList.allCouponDiscount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.goods_promotion_money IS '商品促销产生的优惠金额(如满减、买赠均摊到商品部分)。 | 来源: settleList.goodsPromotionMoney';
-COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_promotion_money IS '助教项目参与活动/促销产生的优惠金额。 | 来源: settleList.assistantPromotionMoney';
-COMMENT ON COLUMN dwd_settlement_head_Ex.activity_discount IS '整单活动折扣金额(如整单打折、满减活动产生的优惠),不区分具体项目类别。 | 来源: settleList.activityDiscount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_manual_discount IS '针对助教服务的人工减免金额,与一般商品/台费折扣区分开。 | 来源: settleList.assistantManualDiscount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_price IS '积分抵扣对应的金额(售价侧),记录因积分使用而减少的应收金额。 | 来源: settleList.pointDiscountPrice';
-COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_cost IS '积分抵扣对应的成本金额(成本侧),用于毛利和利润分析。 | 来源: settleList.pointDiscountCost';
-COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_coupon IS '是否使用优惠券。0=未使用;1=使用。当前样本均为 0。 | 来源: settleList.isUseCoupon';
-COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_discount IS '是否使用折扣(包括会员折扣或其他整单折扣)。0=未使用;1=使用。当前样本多为 0。 | 来源: settleList.isUseDiscount';
-COMMENT ON COLUMN dwd_settlement_head_Ex.is_activity IS '是否参与营销活动。0=未参与;1=参与。 | 来源: settleList.isActivity';
-COMMENT ON COLUMN dwd_settlement_head_Ex.operator_name IS '结账操作员名称快照(通常带角色前缀,如“收银员:张三”),用于报表展示。 | 来源: settleList.operatorName';
-COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_name IS '营业员/业务员名称,用于业绩归属及提成分析;样本中多为空。 | 来源: settleList.salesManName';
-COMMENT ON COLUMN dwd_settlement_head_Ex.order_remark IS '订单备注,由收银员手工填写的文字说明,如特殊情况、赠送原因等,主要用于人工复盘。 | 来源: settleList.orderRemark';
-COMMENT ON COLUMN dwd_settlement_head_Ex.operator_id IS '结账操作员用户 ID,用于关联员工/账号维度(如 dim_staff)。 | 来源: settleList.operatorId | 角色: 外键';
-COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_user_id IS '营业员用户 ID,可关联员工维度,用于业绩分析和提成计算。 | 来源: settleList.salesManUserId | 角色: 外键';
--- dwd_table_fee_log
+COMMENT ON TABLE billiards_dwd.dwd_settlement_head_ex IS 'DWD 明细事实表(扩展字段表):dwd_settlement_head_ex。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - id。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - serialnumber。 【JSON字段】settlement_records.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.settle_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】NULL(状态枚举字段,用于标识业务状态)。 【ODS来源】settlement_records - settlestatus。 【JSON字段】settlement_records.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.can_be_revoked IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - canberevoked(派生:BOOLEAN(canberevoked))。 【JSON字段】settlement_records.json - $ - canberevoked(派生:BOOLEAN(canberevoked))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.revoke_order_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - revokeordername。 【JSON字段】settlement_records.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.revoke_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - revoketime。 【JSON字段】settlement_records.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_first_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isfirst(派生:BOOLEAN(isfirst))。 【JSON字段】settlement_records.json - $ - isfirst(派生:BOOLEAN(isfirst))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - servicemoney。 【JSON字段】settlement_records.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.cash_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - cashamount。 【JSON字段】settlement_records.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - cardamount。 【JSON字段】settlement_records.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.online_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - onlineamount。 【JSON字段】settlement_records.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - refundamount。 【JSON字段】settlement_records.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.prepay_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - prepaymoney。 【JSON字段】settlement_records.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - paymentmethod。 【JSON字段】settlement_records.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.coupon_sale_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - couponsaleamount。 【JSON字段】settlement_records.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.all_coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - allcoupondiscount。 【JSON字段】settlement_records.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - goodspromotionmoney。 【JSON字段】settlement_records.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantpromotionmoney。 【JSON字段】settlement_records.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.activity_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - activitydiscount。 【JSON字段】settlement_records.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.assistant_manual_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - assistantmanualdiscount。 【JSON字段】settlement_records.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.point_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointdiscountprice。 【JSON字段】settlement_records.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.point_discount_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointdiscountcost。 【JSON字段】settlement_records.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_use_coupon IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isusecoupon(派生:BOOLEAN(isusecoupon))。 【JSON字段】settlement_records.json - $ - isusecoupon(派生:BOOLEAN(isusecoupon))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_use_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - isusediscount(派生:BOOLEAN(isusediscount))。 【JSON字段】settlement_records.json - $ - isusediscount(派生:BOOLEAN(isusediscount))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_activity IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isactivity(派生:BOOLEAN(isactivity))。 【JSON字段】settlement_records.json - $ - isactivity(派生:BOOLEAN(isactivity))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - operatorname。 【JSON字段】settlement_records.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - salesmanname。 【JSON字段】settlement_records.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.order_remark IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - orderremark。 【JSON字段】settlement_records.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - operatorid。 【JSON字段】settlement_records.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - salesmanuserid。 【JSON字段】settlement_records.json - $ - salesmanuserid。';
+
+
CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
table_fee_log_id BIGINT,
order_trade_no BIGINT,
@@ -880,35 +1125,37 @@ CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
is_delete INTEGER,
PRIMARY KEY (table_fee_log_id)
);
-COMMENT ON COLUMN dwd_table_fee_log.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_table_fee_log.order_trade_no IS '订单交易号。整笔订单的主编号,用于把同一订单下的台费、商品、助教等多种明细串联在一起。可与支付记录中的交易号对应。 | 来源: order_trade_no | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.order_settle_id IS '结算单号 / 结账 ID。对应一次完整的结账操作。与 dwd_settlement_head 的主键关联。 | 来源: order_settle_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.order_pay_id IS '订单支付记录 ID。对应支付记录中的 id 或 relate_id(视具体模型)。用于追踪这条台费最终对应哪一条支付流水。 | 来源: order_pay_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.tenant_id IS '租户 / 品牌 ID。本文件内所有记录属于同一租户。与其他表的 tenant_id 一致,用于品牌级过滤。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.site_id IS '门店 ID。当前样本为同一门店。与嵌套的 siteProfile.id 以及其他 JSON 中的 site_id 对应,用于门店维度关联。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.site_table_id IS '桌台 ID。对应“台桌基础表”的主键。用于确定具体哪一张台或包厢。 | 来源: site_table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.site_table_area_id IS '门店内“台桌区域” ID(门店视角的区域,如 A 区、B 区、斯诺克区、包厢区)。与门店内部的区域维度对应。 | 来源: site_table_area_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.site_table_area_name IS '台桌区域名称,如 “A区”“B区”“斯诺克区”“VIP包厢” 等。主要用于报表展示和人工阅读。 | 来源: site_table_area_name | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.tenant_table_area_id IS '租户层面的台桌区域 ID。用于品牌层统一定义的区域配置(一个区域可在多门店复用)。对应租户级区域维度。 | 来源: tenant_table_area_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.member_id IS '会员 ID。多数为 0 表示散客。非 0 时表示关联会员:0 表示散客或未使用会员;>0 对应会员档案中的 id。用于将台费流水关联到 dim_member。 | 来源: member_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_name IS '台号名称,例如 “A1”“A2”“S1”“VIP包厢” 等。等价于桌台维表中的展示名称,冗余在流水中作为快照。 | 来源: ledger_name | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_unit_price IS '台费结算时的计费单价(元/小时或元/单位时长)。与 ledger_count 配合计算原始应收台费。常见值如 48.0、58.0、68.0、88.0、98.0、116.0 等。 | 来源: ledger_unit_price | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_count IS '计费时长单位数。与 ledger_unit_price 共同决定原始应收额。可与 real_table_use_seconds 换算关系约为:时长秒数 ≈ ledger_count × 计费粒度(例如 30 分钟、60 分钟)。 | 来源: ledger_count | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_amount IS '原始应收台费金额,按单价与计费时长计算出来的台费金额,尚未考虑会员、券、调账等各类优惠拆分。 | 来源: ledger_amount | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.real_table_charge_money IS '实际向顾客收取的台费金额(现金 / 实付维度),不含券方承担、会员承担和内部调账部分。若为 0,则该笔台费完全由券、会员或内部调账承担。 | 来源: real_table_charge_money | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.coupon_promotion_amount IS '由优惠券、活动、团购等促销承担的优惠金额,直接抵扣在台费上。常见值为与单价或整倍数相同,例如 48.0、96.0、136.0、144.0 等。若 real_table_charge_money 为 0 且该字段等于 ledger_amount,说明台费完全由促销承担。 | 来源: coupon_promotion_amount | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.member_discount_amount IS '由会员权益产生的优惠金额,例如会员折扣、会员免费台等。若 ledger_amount = real_table_charge_money = member_discount_amount,表示这笔台费由会员权益承担,但仍作为台费收入进行记录。 | 来源: member_discount_amount | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.adjust_amount IS '手动减免,调整金额 / 调账金额。用于将台费金额转移或冲减到其他项目(例如套餐、包厢统一计费)或做手工调整。若 ledger_amount 完全被 adjust_amount 抵消,则说明该笔台费被整体调出当前台费科目。 | 来源: adjust_amount | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.real_table_use_seconds IS '台费实际计费时长(秒)。用于计算台费单价与费率分析。内部统一以秒为单位。 | 来源: real_table_use_seconds | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.add_clock_seconds IS '加钟时长(秒)。在原有使用基础上追加的累计加钟时长,常见为 2400、4200 等 60 的倍数(对应 40 分钟、70 分钟等)。 | 来源: add_clock_seconds | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.start_use_time IS '台开始使用时间,即实际开台时间。与 ledger_start_time 相同,表示计费起算点。 | 来源: start_use_time | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_end_time IS '台账计费结束时间。通常与 last_use_time 相差 1 秒。可理解为系统为计费进行的截断时刻。 | 来源: ledger_end_time | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.create_time IS '台费流水记录创建时间,通常接近结账时间。用于区分计费期间与结账时间。 | 来源: create_time | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.ledger_status IS '台费状态。样本中全部为 1。含义:1 表示正常已结算台费。按命名推断,0 可能表示未结算,2 可能表示作废或撤销,需要结合后续数据确认。 | 来源: ledger_status | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.is_single_order IS '是否独立计费单元。枚举:1 表示该记录是独立结算的桌费;0 表示非独立结算条目(可能是合并结账、转台过程中的占位记录)。is_single_order = 0 的记录通常 ledger_count 与 real_table_use_seconds 为 0。 | 来源: is_single_order | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log.is_delete IS '逻辑删除标志。0 表示未删除(有效记录);1 表示已逻辑删除(一般不参与统计)。当前样本全部为 0。 | 来源: is_delete | 角色: 无';
--- dwd_table_fee_log_Ex
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_log IS 'DWD 明细事实表:dwd_table_fee_log。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.table_fee_log_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029058885(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】table_fee_transactions - order_trade_no。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - order_settle_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - order_pay_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - tenant_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_table_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_table_area_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - site_table_area_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791960001957765(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - tenant_table_area_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - member_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A17(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - ledger_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - ledger_unit_price。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - ledger_count。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - ledger_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.real_table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - real_table_charge_money。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_charge_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.coupon_promotion_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - coupon_promotion_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - coupon_promotion_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - member_discount_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - adjust_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - adjust_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.real_table_use_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - real_table_use_seconds。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_use_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.add_clock_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - add_clock_seconds。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - add_clock_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.start_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - start_use_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - start_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - ledger_end_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_end_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - create_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】table_fee_transactions - ledger_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_transactions - is_single_order。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_transactions - is_delete。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_delete。';
+
+
CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
table_fee_log_id BIGINT,
operator_name VARCHAR(64),
@@ -924,20 +1171,22 @@ CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
salesman_org_id BIGINT,
PRIMARY KEY (table_fee_log_id)
);
-COMMENT ON COLUMN dwd_table_fee_log_Ex.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_name IS '操作员姓名。为冗余展示字段,便于直接阅读而不必联表员工档案。 | 来源: operator_name | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_name IS '营业员姓名。当前样本为空。用于需要对营业员维度做业绩统计时作为冗余展示。 | 来源: salesman_name | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.used_card_amount IS '由储值卡、次卡等“卡内余额”直接抵扣到台费的金额。当前样本为 0,但语义明确,用于区分“卡扣款”与“现金收款”。 | 来源: used_card_amount | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.service_money IS '服务费 / 成本 /分成金额字段,类似助教流水里的 service_money。当前样本全为 0,门店未启用该字段,未来可能用于台费附加服务费或分成计算。 | 来源: service_money | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.mgmt_fee IS '管理费字段。当前样本为 0。推测用于未来支持“台费附加管理费”功能。尚未实际启用。 | 来源: mgmt_fee | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.fee_total IS '附加费用合计值字段。当前样本为 0。设计上用于汇总管理费、服务费等附加费用。尚未实际启用。 | 来源: fee_total | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.ledger_start_time IS '台账计费起始时间。当前样本与 start_use_time 相同,表示计费与开台同时开始。 | 来源: ledger_start_time | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.last_use_time IS '最后使用 / 操作时间,通常略晚于 ledger_end_time。可视为客人最后一次用台或最后一次加钟/操作的时间点。 | 来源: last_use_time | 角色: 无';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_id IS '操作员 ID。负责开台 / 结账的员工账号 ID。与员工 / 账号体系中的用户 ID 对应。 | 来源: operator_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_user_id IS '营业员用户 ID。目前样本值为 0,表示门店暂未使用此字段做提成员工归属,但语义清晰。 | 来源: salesman_user_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_org_id IS '营业员所属机构 / 部门 ID。目前样本为 0。用于员工组织结构统计时的归属。 | 来源: salesman_org_id | 角色: 外键';
--- dwd_table_fee_adjust
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_log_ex IS 'DWD 明细事实表(扩展字段表):dwd_table_fee_log_ex。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.table_fee_log_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029058885(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - operator_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - salesman_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.used_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - used_card_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - used_card_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - service_money。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - service_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.mgmt_fee IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - mgmt_fee。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - mgmt_fee。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.fee_total IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - fee_total。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - fee_total。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.ledger_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - ledger_start_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_start_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.last_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - last_use_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - last_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - operator_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - salesman_user_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - salesman_org_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_org_id。';
+
+
CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
table_fee_adjust_id BIGINT,
order_trade_no BIGINT,
@@ -954,21 +1203,23 @@ CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
adjust_time TIMESTAMPTZ,
PRIMARY KEY (table_fee_adjust_id)
);
-COMMENT ON COLUMN dwd_table_fee_adjust.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_table_fee_adjust.order_trade_no IS '订单交易号;与台费流水、结账记录等表中的同名字段一致,用于把本次台费调整挂到具体订单上。 | 来源: order_trade_no | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.order_settle_id IS '结算单 / 小票 ID;与小票、结账头表中的 order_settle_id 对应,用于关联同一次结账。 | 来源: order_settle_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.tenant_id IS '租户 / 品牌 ID;标识该记录属于哪一个商户。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.site_id IS '门店 ID;与 dim_site、其它业务事实表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.table_id IS '台桌 ID;与 dim_table(site_tables_master.id)以及各类台费、助教流水中的 site_table_id 对应,标识哪一张台发生了折扣/调账。 | 来源: site_table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.table_area_id IS '门店维度的台桌区域 ID;与 dim_table 中的 site_table_area_id 对应,例如 “斯诺克区”“VIP包厢”等区域。 | 来源: tableProfile.site_table_area_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.table_area_name IS '台桌区域名称快照,例如 “斯诺克区”“A区”“VIP包厢”;冗余展示字段,可从 dim_table 通过 table_area_id 获取。 | 来源: tableProfile.site_table_area_name';
-COMMENT ON COLUMN dwd_table_fee_adjust.tenant_table_area_id IS '租户维度的“台桌区域 ID”;同一租户下跨门店复用的区域标识,用于在租户级别统计各区域的折扣分布。 | 来源: tenant_table_area_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust.ledger_amount IS '台费调整金额;等于台费流水中对应记录的 adjust_amount。正数表示被减免/调账掉的台费金额(本批数据全部为正);是衡量台费折扣规模的核心度量。 | 来源: ledger_amount';
-COMMENT ON COLUMN dwd_table_fee_adjust.ledger_status IS '调整记录状态(枚举)。1:生效调整(当前有效的折扣/调账记录);0:失效/被覆盖的历史记录(同一订单有多次调整时,旧记录会标记为 0,仅最新一条为 1)。 | 来源: ledger_status';
-COMMENT ON COLUMN dwd_table_fee_adjust.is_delete IS '逻辑删除标记(枚举)。0:未删除(有效记录);1:已逻辑删除(后台标记删除,不再参与业务统计)。当前数据全部为 0,但字段需保留以适配长期数据。 | 来源: is_delete';
-COMMENT ON COLUMN dwd_table_fee_adjust.adjust_time IS '台费调整记录创建时间,即打折/调账操作被系统写入的时间戳,用于时间分析和与结账时间对比(判断是事前折扣还是事后调账)。 | 来源: create_time';
--- dwd_table_fee_adjust_Ex
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_adjust IS 'DWD 明细事实表:dwd_table_fee_adjust。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_fee_adjust_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441881989(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957784612605829(明细字段,用于记录事实取值)。 【ODS来源】table_fee_discount_records - order_trade_no。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913171693253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - order_settle_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - site_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793020259897413(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - site_table_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791961347968901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_table_area_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - tableprofile.table_area_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tableprofile.table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791961347968901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_table_area_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】148.15(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_discount_records - ledger_amount。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】table_fee_discount_records - ledger_status。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_discount_records - is_delete。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.adjust_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:25:11(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_discount_records - create_time。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - create_time。';
+
+
CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
table_fee_adjust_id BIGINT,
adjust_type INTEGER,
@@ -980,16 +1231,18 @@ CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
operator_id BIGINT,
PRIMARY KEY (table_fee_adjust_id)
);
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.adjust_type IS '调整类型(枚举)。当前数据全部为 1。取值示例:1:台费打折 / 台费减免(本门店实际使用的唯一类型);其他值:预留给台费转移、误操作恢复等其他类型(当前未出现,仅推测)。 | 来源: adjust_type';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_count IS '调整次数计数,本数据中恒为 1,表示“一次调整事件”;与台费流水中的 ledger_count(计时长)含义不同。 | 来源: ledger_count';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_name IS '调账项目名称或打折原因名称(设计意图);当前门店所有记录值为空字符串,未实际使用。作用暂不明确,保留以备后续业务启用。 | 来源: ledger_name';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_name IS '申请人姓名快照,通常包含角色前缀(如 “收银员:张三”);是 applicant_id 的冗余展示字段,实际名称应以员工维表为准。 | 来源: applicant_name';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_name IS '操作员姓名快照;与 operator_id 对应的姓名冗余字段。 | 来源: operator_name';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_id IS '申请人 ID;发起本次台费折扣/调账的员工账号 ID,用于按员工维度统计折扣行为。 | 来源: applicant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_id IS '实际执行调账操作的操作员 ID;当前样本中与 applicant_id 相同,但模型上允许“申请人 ≠ 操作人”。 | 来源: operator_id | 角色: 外键';
--- dwd_store_goods_sale
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_adjust_ex IS 'DWD 明细事实表(扩展字段表):dwd_table_fee_adjust_ex。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.table_fee_adjust_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441881989(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.adjust_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】table_fee_discount_records - adjust_type。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - adjust_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_discount_records - ledger_count。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - ledger_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.applicant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - applicant_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - operator_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.applicant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - applicant_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - operator_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_id。';
+
+
CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
store_goods_sale_id BIGINT,
order_trade_no BIGINT,
@@ -1016,31 +1269,33 @@ CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
create_time TIMESTAMPTZ,
PRIMARY KEY (store_goods_sale_id)
);
-COMMENT ON COLUMN dwd_store_goods_sale.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_store_goods_sale.order_trade_no IS '订单交易号(业务单号);与台费、助教、团购等表的 order_trade_no 一致,用于把同一订单下各类消费串联起来。 | 来源: order_trade_no | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.order_settle_id IS '结账记录主键 ID;连接结账记录 / 结算头事实表。 | 来源: order_settle_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.order_pay_id IS '支付记录 ID;连接支付流水事实表,用于还原本条销售对应的收款信息。 | 来源: order_pay_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.order_goods_id IS '当前版本的订单内商品明细 ID;可在订单范围内唯一定位该商品行,用于与小票明细等做行级关联。 | 来源: order_goods_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.site_id IS '门店 ID(系统主键);与其它流水表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.tenant_id IS '租户/品牌 ID;同一品牌下多门店共享同一个 tenant_id。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.site_goods_id IS '门店级商品 ID;连接门店商品档案 dim_store_goods,与库存变动记录中的 siteGoodsId 一致。 | 来源: site_goods_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_id IS '租户级(品牌级)商品 ID;连接租户级商品档案维度表,一个 tenant_goods_id 在不同门店可对应多个 site_goods_id。 | 来源: tenant_goods_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_category_id IS '租户级商品一级分类 ID;连接商品分类维度(如酒水、零食等)。 | 来源: tenant_goods_category_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_business_id IS '租户级商品业务大类 ID(更高一层的业务分类,如“零食类”“酒水类”等)。 | 来源: tenant_goods_business_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.site_table_id IS '球台 ID;非 0 表示该商品在某张台桌上点单,0 表示前台售卖或与台桌无关。连接台桌维度 dim_table。 | 来源: site_table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_name IS '销售项目名称(商品名),如“哇哈哈矿泉水”“地道肠”等;为当时销售时刻的名称快照。 | 来源: ledger_name';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_group_name IS '门店前台菜单分组名称,如“酒水”“零食”“小吃”等;与品牌统一分类是两套维度。 | 来源: ledger_group_name';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_unit_price IS '结算单价(元/单位);本次销售实际使用的单价。 | 来源: ledger_unit_price';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_count IS '销售数量(以商品单位计),如 1、2、6、36 等。 | 来源: ledger_count';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_amount IS '原始应收金额(未考虑任何折扣/抵扣),通常接近 ledger_unit_price × ledger_count。 | 来源: ledger_amount';
-COMMENT ON COLUMN dwd_store_goods_sale.discount_price IS '折后单价(元/单位);无折扣时等于 ledger_unit_price,有折扣时小于 ledger_unit_price。 | 来源: discount_price';
-COMMENT ON COLUMN dwd_store_goods_sale.real_goods_money IS '本行商品实际入账金额(已考虑折扣及其他抵扣后,实际计入营业额的金额);一定不大于 ledger_amount。 | 来源: real_goods_money';
-COMMENT ON COLUMN dwd_store_goods_sale.cost_money IS '本行商品对应的成本金额,用于毛利和利润分析;源自商品档案成本价及成本核算逻辑。 | 来源: cost_money';
-COMMENT ON COLUMN dwd_store_goods_sale.ledger_status IS '销售流水状态:1=正常有效;其他数值(当前数据未出现)一般表示“待结算”“作废”等。 | 来源: ledger_status';
-COMMENT ON COLUMN dwd_store_goods_sale.is_delete IS '逻辑删除标志:0=正常有效;1=已删除(仅保留历史,不再参与前端展示及统计)(本批数据全部为 0)。 | 来源: is_delete';
-COMMENT ON COLUMN dwd_store_goods_sale.create_time IS '销售记录创建时间,通常为结账时间或录入时间;用于时间维度分析,与订单层时间字段对齐。 | 来源: create_time';
--- dwd_store_goods_sale_Ex
+COMMENT ON TABLE billiards_dwd.dwd_store_goods_sale IS 'DWD 明细事实表:dwd_store_goods_sale。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.store_goods_sale_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029550406(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - order_trade_no。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_settle_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_pay_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858456391557(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793026176012357(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792115932417925(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350540(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_category_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_business_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528317768(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_business_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_table_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】哇哈哈矿泉水(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - ledger_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】酒水(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - ledger_group_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_group_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - ledger_unit_price。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_sales_records - ledger_count。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - ledger_amount。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - real_goods_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - real_goods_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.cost_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.01(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - cost_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - cost_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_sales_records - ledger_status。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_sales_records - is_delete。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】store_goods_sales_records - create_time。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - create_time。';
+
+
CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
store_goods_sale_id BIGINT,
legacy_order_goods_id BIGINT,
@@ -1069,38 +1324,41 @@ CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
push_money NUMERIC(18,2),
is_single_order INTEGER,
sales_type INTEGER,
- operator_id BIGINT
+ operator_id BIGINT,
+ PRIMARY KEY (store_goods_sale_id)
);
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_order_goods_id IS '旧版订单商品明细 ID,兼容字段;当前接口已统一使用 order_goods_id,本批数据全部为 0。 | 来源: orderGoodsId';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.site_name IS '门店名称,对 site_id 的冗余文本(例如“朗朗桌球”),用于展示。 | 来源: siteName';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_site_id IS '历史兼容门店 ID;当前接口统一使用 site_id,本批数据 siteId 全部为 0。 | 来源: siteId';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.goods_remark IS '商品备注/口味说明/特殊说明;部分记录为空,部分与商品名相同。 | 来源: goods_remark';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_value_name IS '商品选项名称(规格/口味,如大杯/小杯、不加冰等);当前门店未启用多规格,样本中全部为空。 | 来源: option_value_name';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_name IS '操作员姓名冗余,如“收银员:郑丽珊”;用于展示,不作为关联键。 | 来源: operator_name';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.open_salesman_flag IS '是否启用营业员机制标志:1=启用营业员/提成体系(需指定 salesman_* 字段);2=未启用营业员体系(本批数据全部为 2)。 | 来源: openSalesman';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_user_id IS '营业员用户 ID(系统账号 ID);当前样本全部为 0,说明门店未启用营业员业绩统计。 | 来源: salesman_user_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_name IS '营业员姓名;当前样本全部为空字符串。 | 来源: salesman_name';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_role_id IS '营业员角色 ID(例如某角色代码对应“销售员”角色);当前样本全部为 0。 | 来源: salesman_role_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_org_id IS '营业员所属组织/部门 ID;当前样本全部为 0,未启用按组织分组统计。 | 来源: sales_man_org_id | 角色: 外键';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.discount_money IS '本行商品的直接价格优惠金额(打折让利部分);在简单场景下满足:ledger_amount − discount_money ≈ real_goods_money(不含积分、券抵扣)。 | 来源: discount_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.returns_number IS '退货数量;当前样本全部为 0,如发生退货则记录退回的件数。 | 来源: returns_number';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.coupon_deduct_money IS '优惠券/团购券直接抵扣到本条商品明细上的金额;当前样本为 0,说明券更多在订单级处理。 | 来源: coupon_deduct_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_discount_amount IS '由会员折扣针对本行商品产生的优惠金额;当前样本全部为 0,折扣通常体现在 discount_money 中。 | 来源: member_discount_amount';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money IS '由积分抵扣的金额(顾客用积分兑换的抵现金额)。 | 来源: point_discount_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money_cost IS '积分抵扣对应的成本金额(积分成本、营销费用等核算用)。 | 来源: point_discount_money_cost';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.package_coupon_id IS '套餐券 ID;当商品来自套餐拆分或与套餐券关联时,用于追溯对应的套餐业务(当前样本为 0)。 | 来源: package_coupon_id';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.order_coupon_id IS '订单级优惠券 ID;整单使用某张券时,可用于记录该券对本行商品的分摊关系(当前样本为 0)。 | 来源: order_coupon_id';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_coupon_id IS '会员券 ID(如会员专享优惠券);当前样本为 0,为会员权益预留字段。 | 来源: member_coupon_id';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_price IS '商品选项(规格/加料等)的附加价格;当前门店未启用此功能,样本为 0。 | 来源: option_price';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_member_discount_money IS '由会员折扣作用在“选项价格”上的优惠金额;当前样本为 0。 | 来源: option_member_discount_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_coupon_deduct_money IS '由优惠券抵扣“选项价格”的金额;当前样本为 0。 | 来源: option_coupon_deduct_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.push_money IS '本行商品对应的提成金额(营业员/业务员提成);当前样本为 0,说明提成体系未启用。 | 来源: push_money';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.is_single_order IS '是否作为独立明细参与订单结算:1=作为独立明细参与订单;0=在特殊业务中可能合并为打包项目(当前样本全部为 1)。 | 来源: is_single_order';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.sales_type IS '销售类型:1=正常销售(当前样本全部为 1);常见扩展用法:2=赠品;3=内部消耗;4=盘点调整等。 | 来源: sales_type';
-COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_id IS '操作员 ID(录入本条销售的员工);与其它流水中的 operator_id 一致,可统一做员工维度分析。 | 来源: operator_id | 角色: 外键';
--- dwd_assistant_service_log
+COMMENT ON TABLE billiards_dwd.dwd_store_goods_sale_ex IS 'DWD 明细事实表(扩展字段表):dwd_store_goods_sale_ex。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.store_goods_sale_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029550406(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.legacy_order_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858456391557(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - siteName。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - siteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.legacy_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.goods_remark IS '【说明】明细字段,用于记录事实取值。 【示例】哇哈哈矿泉水(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - goods_remark。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - goods_remark。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_value_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - option_value_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_value_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - operator_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.open_salesman_flag IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - openSalesman。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - openSalesman。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - salesman_user_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - salesman_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - salesman_role_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_role_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - sales_man_org_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_man_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.returns_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_sales_records - returns_number。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - returns_number。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - coupon_deduct_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - member_discount_amount。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.point_discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - point_discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.point_discount_money_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - point_discount_money_cost。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money_cost。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.package_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - package_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - package_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.order_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.member_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - member_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_price。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_member_discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_member_discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_member_discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_coupon_deduct_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.push_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - push_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - push_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_sales_records - is_single_order。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.sales_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - sales_type。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - operator_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_id。';
+
+
CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
assistant_service_id BIGINT,
order_trade_no BIGINT,
@@ -1136,40 +1394,42 @@ CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
is_delete INTEGER,
PRIMARY KEY (assistant_service_id)
);
-COMMENT ON COLUMN dwd_assistant_service_log.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_assistant_service_log.order_trade_no IS '订单交易号,用于与台费、商品、支付等同一订单下的其他明细串联。 | 来源: order_trade_no | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.order_settle_id IS '结算单号,对应结账记录、小票中的结算主键。 | 来源: order_settle_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.order_pay_id IS '支付记录主键 ID,用于关联支付流水。 | 来源: order_pay_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_id IS '订单中“助教项目明细”的内部 ID,一笔订单中多段助教服务时用于区分。 | 来源: order_assistant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_type IS '助教服务类型枚举:1 表示常规助教服务(如基础课);2 表示附加类助教服务(如附加课);其他值预留。 | 来源: order_assistant_type';
-COMMENT ON COLUMN dwd_assistant_service_log.tenant_id IS '租户/品牌 ID,用于区分商户。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.site_id IS '门店 ID,对应门店维表中的门店主键。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.site_table_id IS '球台/包厢 ID,对应台桌维表主键。 | 来源: site_table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.tenant_member_id IS '商户维度会员 ID,对应会员档案主键;0 表示非会员或散客。 | 来源: tenant_member_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.system_member_id IS '系统级会员 ID,用于跨门店识别同一会员。 | 来源: system_member_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.assistant_no IS '助教编号/工号,如 “27”;与助教档案中的工号一致。 | 来源: assistantNo';
-COMMENT ON COLUMN dwd_assistant_service_log.nickname IS '助教对外昵称,如“佳怡”“周周”;用于展示,不参与业务逻辑。 | 来源: nickname';
-COMMENT ON COLUMN dwd_assistant_service_log.site_assistant_id IS '门店维度助教 ID,对应助教账号维表主键。 | 来源: site_assistant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.user_id IS '助教对应的系统用户 ID,对应账号体系中的 user_id。 | 来源: user_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.assistant_team_id IS '助教团队 ID,用于分组统计团队业绩。 | 来源: assistant_team_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.person_org_id IS '助教所属人事组织/部门 ID,如“助教部”;用于组织维度分析。 | 来源: person_org_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.assistant_level IS '助教等级编码:8=助教管理;10=初级;20=中级;30=高级;用于薪酬/评价分层。 | 来源: assistant_level | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.level_name IS '助教等级名称,与 assistant_level 对应,如“初级”“中级”“高级”“助教管理”。 | 来源: levelName';
-COMMENT ON COLUMN dwd_assistant_service_log.skill_id IS '助教服务课程/技能 ID,应对应课程/技能配置表。 | 来源: skill_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log.skill_name IS '助教服务课程/技能名称,如“基础课”“附加课”。 | 来源: skillName';
-COMMENT ON COLUMN dwd_assistant_service_log.ledger_unit_price IS '助教服务标准单价(原价),例如按小时或按节课的标价。 | 来源: ledger_unit_price';
-COMMENT ON COLUMN dwd_assistant_service_log.ledger_amount IS '按标准单价计算的应收金额,近似等于 ledger_unit_price×计费时长换算后的金额。 | 来源: ledger_amount';
-COMMENT ON COLUMN dwd_assistant_service_log.projected_income IS '实际计入门店收入的金额,已经考虑会员权益、券抵扣等后的结果。 | 来源: projected_income';
-COMMENT ON COLUMN dwd_assistant_service_log.coupon_deduct_money IS '由优惠券、团购券等直接抵扣到本次助教服务上的金额;0 表示未使用券。 | 来源: coupon_deduct_money';
-COMMENT ON COLUMN dwd_assistant_service_log.income_seconds IS '计费秒数(用于计算应收收入的时间长度),通常为按分钟取整的秒数。 | 来源: income_seconds';
-COMMENT ON COLUMN dwd_assistant_service_log.real_use_seconds IS '实际服务时长(秒),真实消耗的时间,用于分析助教工作量。 | 来源: real_use_seconds';
-COMMENT ON COLUMN dwd_assistant_service_log.add_clock IS '加钟秒数,在原有预约基础上临时增加的服务时间,数值为 60 的倍数。 | 来源: add_clock';
-COMMENT ON COLUMN dwd_assistant_service_log.create_time IS '助教流水记录创建时间,接近下单/结算时间。 | 来源: create_time';
-COMMENT ON COLUMN dwd_assistant_service_log.start_use_time IS '助教实际开始服务时间,通常与 ledger_start_time 一致。 | 来源: start_use_time';
-COMMENT ON COLUMN dwd_assistant_service_log.last_use_time IS '助教最后一次服务时间,通常与 ledger_end_time 一致。 | 来源: last_use_time';
-COMMENT ON COLUMN dwd_assistant_service_log.is_delete IS '逻辑删除标志:0 未删除;1 已逻辑删除,用于保留历史数据。 | 来源: is_delete';
--- dwd_assistant_service_log_Ex
+COMMENT ON TABLE billiards_dwd.dwd_assistant_service_log IS 'DWD 明细事实表:dwd_assistant_service_log。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_service_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441292165(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957784612605829(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - order_trade_no。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913171693253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_settle_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_pay_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957788717240005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_assistant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_assistant_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - order_assistant_type。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - tenant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - site_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793020259897413(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - site_table_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - tenant_member_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - system_member_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_no IS '【说明】明细字段,用于记录事实取值。 【示例】27(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - assistantNo。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantNo。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - nickname。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - nickname。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957788717240005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_assistant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2946266868976453(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - user_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_team_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792011585884037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - assistant_team_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_team_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.person_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2946266869336901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - person_org_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - person_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_level IS '【说明】明细字段,用于记录事实取值。 【示例】10(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - assistant_level。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_level。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.level_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】初级(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - levelName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - levelName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.skill_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683529513797(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - skill_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.skill_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】基础课(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - skillName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skillName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】98.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - ledger_unit_price。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】206.67(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - ledger_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.projected_income IS '【说明】明细字段,用于记录事实取值。 【示例】168.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - projected_income。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - projected_income。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - coupon_deduct_money。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.income_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】7560(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - income_seconds。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - income_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.real_use_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】7592(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - real_use_seconds。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - real_use_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.add_clock IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - add_clock。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - add_clock。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:25:11(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - create_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.start_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 21:18:18(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - start_use_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - start_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.last_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:24:50(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - last_use_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - last_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_delete。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_delete。';
+
+
CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
assistant_service_id BIGINT,
table_name VARCHAR(64),
@@ -1203,38 +1463,40 @@ CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
composite_grade_time TIMESTAMPTZ,
PRIMARY KEY (assistant_service_id)
);
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.table_name IS '球台名称,如 “A17”“S1”,与 site_table_id 冗余,用于展示。 | 来源: tableName';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_name IS '助教姓名,如“何海婷”;与助教档案中的真实姓名一致。 | 来源: assistantName';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_name IS '助教计费项目名称,如“2-佳怡”等,通常为展示用组合字段。 | 来源: ledger_name';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_group_name IS '助教项目所属的计费分组/套餐分组名称,目前导出数据中为空,未看到实际使用场景。 | 来源: ledger_group_name';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_count IS '台账计费时长(秒),通常与 real_use_seconds 接近或相等。取income_seconds TEXT';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.member_discount_amount IS '由会员卡折扣产生的优惠金额,当前样本中为 0,但字段语义明确。 | 来源: member_discount_amount';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.manual_discount_amount IS '收银员手动减免金额(人工改价);当前导出数据中为 0。 | 来源: manual_discount_amount';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_money IS '与助教结算的金额或服务成本金额,当前数据全部为 0,具体结算规则未见启用。 | 来源: service_money';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.returns_clock IS '退钟秒数(取消加钟或提前结束退回的时间),当前样本中全部为 0,未见业务使用。 | 来源: returns_clock';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_start_time IS '台账计费起始时间。 | 来源: ledger_start_time';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_end_time IS '台账计费结束时间,可作为本次服务结束时间。 | 来源: ledger_end_time';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_status IS '助教流水状态:当前数据为 1,表示正常有效;其他值预留给已作废、未结算等状态。 | 来源: ledger_status';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_confirm IS '确认状态:当前样本为 2,一般含义为 1=待确认,2=已确认/已完成(含义基于字段名和现有值推断)。 | 来源: is_confirm';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_single_order IS '是否单独订单:1 表示助教服务作为单独订单结算;0 表示与其他项目合单结算。当前样本全部为 1。 | 来源: is_single_order';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_not_responding IS '是否存在“未响应/爽约”等异常:0 表示正常;1 表示未响应或爽约(基于字段名推断,当前数据均为 0)。 | 来源: is_not_responding';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_trash IS '是否已废除:0 表示正常有效;1 表示已废除,与助教废除记录表(assistant_cancellation_records)对应。 | 来源: is_trash';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_id IS '提出废除申请的员工 ID,用于追溯谁发起了废除操作。 | 来源: trash_applicant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_name IS '废除申请人姓名,仅用于展示,与 trash_applicant_id 冗余。 | 来源: trash_applicant_name';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_reason IS '废除原因文案,如“顾客取消”“录入错误”,便于分析异常原因。 | 来源: trash_reason';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_user_id IS '营业员/销售员用户 ID,大多为 0,当前门店未明显使用此维度。 | 来源: salesman_user_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_name IS '营业员/销售员姓名,多数为空字符串。 | 来源: salesman_name';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_org_id IS '营业员所属组织/部门 ID,多数为 0,尚未看到实际业务使用。 | 来源: salesman_org_id | 角色: 外键';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.skill_grade IS '课程技能评分(整数),当前样本全为 0,评价功能尚未启用。 | 来源: skill_grade';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_grade IS '服务态度评分(整数),当前样本全为 0。 | 来源: service_grade';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade IS '综合评分(技能+服务等加权结果),当前样本为 0。 | 来源: composite_grade';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.sum_grade IS '累计评分总和,用于计算平均分,当前样本为 0。 | 来源: sum_grade';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.get_grade_times IS '获得评价的次数,当前样本为 0。 | 来源: get_grade_times';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.grade_status IS '评价状态枚举:当前样本为 1,一般含义为“未评价/正常”,其他状态未见实际值。 | 来源: grade_status';
-COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade_time IS '最近一次综合评分时间或评价更新时间,当前为默认时间 “0001-01-01 00:00:00”。 | 来源: composite_grade_time';
--- dwd_assistant_trash_event
+COMMENT ON TABLE billiards_dwd.dwd_assistant_service_log_ex IS 'DWD 明细事实表(扩展字段表):dwd_assistant_service_log_ex。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.assistant_service_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441292165(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】S1(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - tableName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.assistant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】何海婷(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - assistantName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】27-泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - ledger_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - ledger_group_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_group_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】7592(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - ledger_count。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - member_discount_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.manual_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - manual_discount_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - manual_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - service_money。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.returns_clock IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - returns_clock。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - returns_clock。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 21:18:18(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - ledger_start_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_start_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:24:50(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - ledger_end_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_end_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_service_records - ledger_status。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_confirm IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】2(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_confirm。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_confirm。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_single_order。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_not_responding IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_not_responding。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_not_responding。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_trash IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_trash。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_trash。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_applicant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - trash_applicant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_applicant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - trash_applicant_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_reason IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - trash_reason。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_reason。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - salesman_user_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - salesman_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - salesman_org_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.skill_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - skill_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.service_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - service_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.composite_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - composite_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.sum_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - sum_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - sum_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.get_grade_times IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - get_grade_times。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - get_grade_times。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.grade_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_service_records - grade_status。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - grade_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.composite_grade_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - composite_grade_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade_time。';
+
+
CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
assistant_trash_event_id BIGINT,
site_id BIGINT,
@@ -1248,29 +1510,33 @@ CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
create_time TIMESTAMPTZ,
PRIMARY KEY (assistant_trash_event_id)
);
-COMMENT ON COLUMN dwd_assistant_trash_event.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_assistant_trash_event.site_id IS '门店 ID。与其他 JSON 中的 siteId / site_id 含义一致。用来关联 dim_site。当前样例全部为同一门店(朗朗桌球),但设计上支持多门店。 | 来源: siteId | 角色: 外键(指向 dim_site)';
-COMMENT ON COLUMN dwd_assistant_trash_event.table_id IS '台桌 ID。对应 site_tables_master.json 中的 id。用于定位哪一张球台发生了助教废除,用于后续软关联台费流水、助教流水时的重要条件。 | 来源: tableId | 角色: 外键(指向 dim_table)';
-COMMENT ON COLUMN dwd_assistant_trash_event.table_area_id IS '台桌区域 ID。应与台桌维或区域维中的 area_id 一致,用于按区域统计(A 区/B 区/VIP 包厢等)。 | 来源: tableAreaId | 角色: 外键(潜在指向 dim_table_area)';
-COMMENT ON COLUMN dwd_assistant_trash_event.assistant_no IS '助教编号(工号/序号),如 ''2''、''4''、''27'' 等。与助教档案表 assistant_accounts_master.assistant_no、助教流水中的 assistantNo 一致,用于标识哪位助教。枚举:在门店内是有限编号集合,但并非硬编码含义。 | 来源: assistantOn | 角色: 外键(指向 dim_assistant)';
-COMMENT ON COLUMN dwd_assistant_trash_event.assistant_name IS '助教姓名/昵称,如 “泡芙”“佳怡”等。为冗余展示字段,真实姓名以助教档案为准。当前数据中与档案一致。 | 来源: assistantName';
-COMMENT ON COLUMN dwd_assistant_trash_event.charge_minutes_raw IS '助教被废除前“已计费时长(分钟)”的原始值。单位为分钟。示例:214、3600、10800 等。0 表示尚未发生有效计费就被废除。当前数据中存在异常大值(例如 10800),这一业务含义需结合实际规则理解,但本字段原样保留。枚举:数值型,无固定枚举。 | 来源: pdChargeMinutes';
-COMMENT ON COLUMN dwd_assistant_trash_event.abolish_amount IS '与本次助教废除操作关联的金额,单位元。字面含义为“助教废除金额”。当前样例均为非负数,如 5.83、570.00、0.00 等。正负方向:按照 ODS/JSON 原样保留,暂不在数仓层赋予“收入/支出”的方向含义,后续在 DWS 层按业务规则解释(例如是退还顾客、扣除收益等)。 | 来源: assistantAbolishAmount';
-COMMENT ON COLUMN dwd_assistant_trash_event.trash_reason IS '废除原因的文本说明,例如可以写“顾客临时取消”“误操作”等。当前样例中全部为空字符串,说明前台并未使用该字段。但从结构上看,是一个自由文本字段,不是枚举。 | 来源: trashReason';
-COMMENT ON COLUMN dwd_assistant_trash_event.create_time IS '这条废除记录创建的时间,格式 YYYY-MM-DD HH:MM:SS。代表系统正式记录“废除操作”的时刻,用于和助教服务流水按时间窗口做软关联(结合 site、table、assistant 等条件)。 | 来源: createTime';
--- dwd_assistant_trash_event_Ex
+COMMENT ON TABLE billiards_dwd.dwd_assistant_trash_event IS 'DWD 明细事实表:dwd_assistant_trash_event。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_trash_event_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957675849518789(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - id。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - siteId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793016660660357(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - tableId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963816579205(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - tableAreaId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableAreaId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_no IS '【说明】明细字段,用于记录事实取值。 【示例】泡芙(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - assistantName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - assistantName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.charge_minutes_raw IS '【说明】明细字段,用于记录事实取值。 【示例】214(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - pdChargeMinutes。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - pdChargeMinutes。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.abolish_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.83(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_cancellation_records - assistantAbolishAmount。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantAbolishAmount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.trash_reason IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - trashReason。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - trashReason。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 19:23:29(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_cancellation_records - createTime。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - createTime。';
+
+
CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event_Ex (
assistant_trash_event_id BIGINT,
table_name VARCHAR(64),
table_area_name VARCHAR(64),
PRIMARY KEY (assistant_trash_event_id)
);
-COMMENT ON COLUMN dwd_assistant_trash_event_Ex.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_name IS '台桌名称/编号,便于直观看报表,如 “C1”“B9”“VIP1”等。文案冗余自台桌维度。枚举:在门店范围内是有限集合,但不是固定编码表。 | 来源: tableName';
-COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_area_name IS '台桌区域名称(中文),如 “A区”“B区”“C区”“VIP包厢”“补时长”等。展示用文本,具体层级信息由区域维表提供。 | 来源: tableArea';
--- dwd_member_balance_change
+COMMENT ON TABLE billiards_dwd.dwd_assistant_trash_event_ex IS 'DWD 明细事实表(扩展字段表):dwd_assistant_trash_event_ex。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.assistant_trash_event_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957675849518789(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - id。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】C1(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - tableName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】C区(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - tableArea。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableArea。';
+
+
CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
balance_change_id BIGINT,
tenant_id BIGINT,
@@ -1293,27 +1559,29 @@ CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
remark VARCHAR(255),
PRIMARY KEY (balance_change_id)
);
-COMMENT ON COLUMN dwd_member_balance_change.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_member_balance_change.tenant_id IS '租户/品牌 ID,在整体系统中唯一标识一家商户。当前样本中为同一值。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.site_id IS '本次余额变动发生的门店 ID。通常对应具体门店;样本中:非 0 为“朗朗桌球”,0 代表平台级/虚拟门店场景(如活动抵用券结算)。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.register_site_id IS '办卡门店 ID(卡注册门店)。与 site_id 区分:register_site_id=当初办卡门店,site_id=本次余额变动实际发生门店。当前样本中全部相同。 | 来源: register_site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.tenant_member_id IS '租户维度会员 ID(同一租户内的会员主键),用于关联会员档案。 | 来源: tenant_member_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.system_member_id IS '系统全局会员 ID(跨租户统一的会员标识)。当前只有一个门店,但结构上允许同一人跨租户共享该 ID。 | 来源: system_member_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.tenant_member_card_id IS '会员卡账户 ID(租户内唯一的一张具体卡,例如某人的储值卡/酒水卡/台费卡/活动抵用券等)。本次余额变动作用于这张卡。 | 来源: tenant_member_card_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.card_type_id IS '卡种类型 ID。与 card_type_name 一一对应,用于区分不同卡种(储值卡/活动抵用券/酒水卡/台费卡)。 | 来源: card_type_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change.card_type_name IS '卡种名称(中文):• 储值卡:通用储值卡;• 活动抵用券:活动送券型卡;• 酒水卡:指定用于酒水类消费;• 台费卡:指定用于台费消费。 | 来源: memberCardTypeName';
-COMMENT ON COLUMN dwd_member_balance_change.member_name IS '会员姓名/称呼(如“曾丹烨”“葛先生”“胡先生”),主要用于运营、客服和人工识别。 | 来源: memberName';
-COMMENT ON COLUMN dwd_member_balance_change.member_mobile IS '会员手机号(完整号码字符串),是会员识别、营销触达的重要字段。 | 来源: memberMobile';
-COMMENT ON COLUMN dwd_member_balance_change.balance_before IS '本次变动前的卡内余额,单位:元。可为 0、数百、数千等。 | 来源: before';
-COMMENT ON COLUMN dwd_member_balance_change.change_amount IS '本次余额变动金额,单位:元:• 正数:余额增加(充值、赠送、调整加款等);• 负数:余额减少(消费扣款、退款冲减、活动抵扣等)。所有记录严格满足:balance_after = balance_before + change_amount(浮点精度内)。 | 来源: account_data';
-COMMENT ON COLUMN dwd_member_balance_change.balance_after IS '本次变动后的卡内余额,单位:元。由 before + account_data 计算而得,在源数据中已给出。 | 来源: after';
-COMMENT ON COLUMN dwd_member_balance_change.from_type IS '余额变动来源类型枚举(控制业务含义与方向):• 1:日常消费扣款 —— change_amount 为负数,payment_method=0,表示用卡支付消费被扣余额;• 3:充值增加 —— change_amount 为正数,payment_method=4,表示顾客通过外部支付为卡充值(扫码、银行卡等);• 4:调整/赠送增加 —— change_amount 为正数,payment_method=3,通常为后台赠送或手工加款;• 7:充值退款 —— change_amount 为负数,remark=''充值退款'',表示对历史充值做退款,以减少卡内余额方式体现;• 9:活动抵用券相关余额冲减 —— change_amount 为负数,卡种为“活动抵用券”,site_id=0,表示活动券额度被扣回或结算;• 2:其他增加 —— 当前仅 1 条正数样本(+1865.80),具体业务类型不明,但可确定为余额增加类。总体上:1/7/9 为减余额类,2/3/4 为加余额类。 | 来源: from_type';
-COMMENT ON COLUMN dwd_member_balance_change.payment_method IS '支付/变动渠道枚举(与源系统支付方式枚举一致):• 0:内部结算/无外部支付 —— 日常消费扣款、内部扣减、退款冲减等场景,新资金流不在本记录中产生;• 3:赠送/后台调整渠道 —— 与 from_type=4 搭配出现,表示此余额增加不是顾客付钱,而是后台发放或内部调账;• 4:充值外部支付渠道 —— 与 from_type=3 搭配出现,代表顾客通过某外部渠道完成充值(具体是微信/支付宝/银行卡等需要结合支付枚举表进一步映射)。 | 来源: payment_method';
-COMMENT ON COLUMN dwd_member_balance_change.change_time IS '余额变动时间(记录创建时间),格式 YYYY-MM-DD HH:MM:SS。通常紧邻实际交易发生时间,用于按时间线分析资金变动。 | 来源: create_time';
-COMMENT ON COLUMN dwd_member_balance_change.is_delete IS '逻辑删除标记:• 0:正常记录(当前样本全部为 0);• 1:逻辑删除(标记为删除但数据库保留,用于追溯)。分析时通常需要过滤掉 is_delete=1 的记录。 | 来源: is_delete';
-COMMENT ON COLUMN dwd_member_balance_change.remark IS '余额变动备注信息。当前样本中主要为:• 空字符串:无额外说明;• 充值退款:明确标记该条记录为“充值退款”业务,与 from_type=7 完全对应。后续可能出现其他业务备注。 | 来源: remark';
--- dwd_member_balance_change_EX
+COMMENT ON TABLE billiards_dwd.dwd_member_balance_change IS 'DWD 明细事实表:dwd_member_balance_change。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_change_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957881605869253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - site_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - register_site_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799212845565701(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_member_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799212844549893(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - system_member_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799219999295237(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_member_card_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_card_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.card_type_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793249295533893(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - card_type_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - card_type_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】储值卡(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - memberCardTypeName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberCardTypeName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】曾丹烨(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - memberName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.member_mobile IS '【说明】明细字段,用于记录事实取值。 【示例】13922213242(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - memberMobile。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberMobile。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_before IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】816.3(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - before。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - before。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.change_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】-120.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - account_data。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - account_data。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_after IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】696.3(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - after。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - after。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.from_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - from_type。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - from_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - payment_method。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.change_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:52:48(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_balance_changes - create_time。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_balance_changes - is_delete。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.remark IS '【说明】明细字段,用于记录事实取值。 【示例】充值退款(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - remark。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - remark。';
+
+
CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
balance_change_id BIGINT,
pay_site_name VARCHAR(64),
@@ -1323,14 +1591,16 @@ CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
operator_name VARCHAR(64),
PRIMARY KEY (balance_change_id)
);
-COMMENT ON COLUMN dwd_member_balance_change_EX.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_member_balance_change_EX.pay_site_name IS '余额变动发生门店名称,对应 site_id 的中文名。示例:朗朗桌球;当 site_id = 0 时通常为空字符串。纯展示冗余。 | 来源: paySiteName';
-COMMENT ON COLUMN dwd_member_balance_change_EX.register_site_name IS '办卡门店名称,对应 register_site_id 的中文名。当前样本全部为 朗朗桌球,属于冗余展示。 | 来源: registerSiteName';
-COMMENT ON COLUMN dwd_member_balance_change_EX.refund_amount IS '退款金额字段。在当前样本数据中全部为 0.00,推测用于区分“退回卡内余额”和“原路退回”等更细的退款模式,但目前未启用。 | 来源: refund_amount';
-COMMENT ON COLUMN dwd_member_balance_change_EX.operator_id IS '操作员 ID,执行本次余额变动操作的员工账号主键。可关联员工/账号维度。 | 来源: operator_id | 角色: 外键';
-COMMENT ON COLUMN dwd_member_balance_change_EX.operator_name IS '操作员名称及职位说明,例如:收银员:郑丽珊、店长:谢晓洪 等,是对 operator_id 的可读冗余。 | 来源: operator_name';
--- dwd_groupbuy_redemption
+COMMENT ON TABLE billiards_dwd.dwd_member_balance_change_ex IS 'DWD 明细事实表(扩展字段表):dwd_member_balance_change_ex。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.balance_change_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957881605869253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.pay_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - paySiteName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - paySiteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.register_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - registerSiteName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - registerSiteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - refund_amount。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - refund_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - operator_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - operator_name。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_name。';
+
+
CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
redemption_id BIGINT,
tenant_id BIGINT,
@@ -1357,31 +1627,33 @@ CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
create_time TIMESTAMPTZ,
PRIMARY KEY (redemption_id)
);
-COMMENT ON COLUMN dwd_groupbuy_redemption.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_id IS '租户/品牌 ID。与其他表统一的租户标识,用于品牌维度聚合。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.site_id IS '门店 ID。与门店维度及其他业务事实中的 site_id 一致。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.table_id IS '球台 ID。与台桌维度表中的 id 对应,用于确定具体哪一张球台。 | 来源: table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_table_area_id IS '租户级台区组合 ID。与团购套餐定义中的 tenant_table_area_id_list 元素对应,表示该券实际使用时所在的台区组合。用于校验券的适用台区是否匹配实际台桌。 | 来源: tenant_table_area_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.table_charge_seconds IS '本次结算中该球台总计计费的秒数(整台计费时间)。当台上除了券覆盖时长之外还有额外计费时间时,该值会大于券核销时长。 | 来源: table_charge_seconds';
-COMMENT ON COLUMN dwd_groupbuy_redemption.order_trade_no IS '订单交易号。与台费流水、商品销售、助教服务、小票详情等表的 order_trade_no 一致,用于将同一笔结账中的所有明细串联起来。 | 来源: order_trade_no | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.order_settle_id IS '结算单 ID。与结账记录和小票详情中的结算主键对应,用于从团购券核销记录跳转到整单结算。 | 来源: order_settle_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_id IS '订单中的“券使用记录 ID”。与平台或内部券核销表中的主键一致,用于在订单内部定位这条券使用记录。当前与 coupon_origin_id 数值相等。 | 来源: order_coupon_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_origin_id IS '上游系统或第三方平台中该券记录的主键 ID。可在平台验券记录中查到券的来源平台、原订单等。当前与 order_coupon_id 数值一致,但语义是“券来源 ID”。 | 来源: coupon_origin_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_activity_id IS '促销活动 ID。每条记录对应一个活动主键,用于识别券所属的促销活动或团购活动。 | 来源: promotion_activity_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_coupon_id IS '团购套餐定义 ID。与 group_buy_packages.json 中的 id 一一对应,表示当前使用的是哪一种团购套餐(例如某款“一小时套餐”“两小时套餐”)。 | 来源: promotion_coupon_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_channel IS '券渠道类型枚举。观测值:1(大量记录)、2(少量记录)。用于区分券的来源渠道,例如不同团购平台或内部券。具体数值与渠道名称的映射由业务配置决定。 | 来源: order_coupon_channel | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_unit_price IS '本次券在台费侧对应的标准单价,单位元/小时。典型值如 29.9、39.9、59.9、69.9 等。与门店台费计费规则中的单价相对应,用于计算券对应的金额。 | 来源: ledger_unit_price';
-COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_count IS '本次券实际核销的计费秒数。大部分记录等于 promotion_seconds,少数略小于标准时长,表示这张券只覆盖了本次台费的一部分时长。 | 来源: ledger_count';
-COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_amount IS '本次团购券实际冲抵台费的金额。大部分记录中该值与 coupon_money 相等,少数存在小数差异,来源于按单价与秒数换算的结果。 | 来源: ledger_amount';
-COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_money IS '本次核销时,团购券在门店侧对应的金额额度(可抵扣金额)。同一种 promotion_coupon_id 下,该值固定,例如某套餐固定为 48.00 元、某套餐固定为 96.00 元等。 | 来源: coupon_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_seconds IS '团购套餐定义的标准时长权益,单位秒。观测枚举值为 3600、7200、14400,分别对应 1 小时、2 小时、4 小时。与团购套餐定义表中的 duration 字段一致。 | 来源: promotion_seconds';
-COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_code IS '团购券券码字符串。每条记录一个唯一券码,例如“0107892475999”。用于与平台验券记录、券购买记录等做一一对应,追踪券的全生命周期。 | 来源: coupon_code | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption.is_single_order IS '是否作为单独订单行。观测值:1 为主,表示以独立条目方式结算;0 为个别记录,表示嵌入某种组合结算结构。具体业务含义依赖上层订单结构设计。 | 来源: is_single_order';
-COMMENT ON COLUMN dwd_groupbuy_redemption.is_delete IS '逻辑删除标记。0 表示正常记录,1 表示逻辑删除但数据仍保留用于追溯。当前样本全部为 0,用于过滤有效记录。 | 来源: is_delete';
-COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_name IS '团购项目记账名称,如“全天A区中八一小时”“B区桌球一小时”“中八、斯诺克包厢两小时”等。通常与团购套餐名称相近,用于报表展示和套餐维度分析。 | 来源: ledger_name';
-COMMENT ON COLUMN dwd_groupbuy_redemption.create_time IS '本条团购券核销流水的创建时间,通常即核销时间,格式为“YYYY-MM-DD HH:MM:SS”。用于时间维度分析和数据分区。 | 来源: create_time';
--- dwd_groupbuy_redemption_Ex
+COMMENT ON TABLE billiards_dwd.dwd_groupbuy_redemption IS 'DWD 明细事实表:dwd_groupbuy_redemption。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029615941(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - tenant_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - site_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - table_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791960001957765(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - tenant_table_area_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.table_charge_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - table_charge_seconds。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_charge_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - order_trade_no。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_settle_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858168229573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_coupon_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_origin_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858168229573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - coupon_origin_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_origin_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_activity_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858166460101(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - promotion_activity_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_activity_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2798727423528005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - promotion_coupon_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_coupon_channel IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - order_coupon_channel。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】29.9(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - ledger_unit_price。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - ledger_count。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - ledger_amount。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - coupon_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - promotion_seconds。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_code IS '【说明】明细字段,用于记录事实取值。 【示例】0107892475999(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - coupon_code。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_code。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_redemption_records - is_single_order。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_redemption_records - is_delete。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】全天A区中八一小时(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - ledger_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_redemption_records - create_time。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - create_time。';
+
+
CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
redemption_id BIGINT,
site_name VARCHAR(64),
@@ -1406,29 +1678,31 @@ CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
ledger_group_name VARCHAR(128),
PRIMARY KEY (redemption_id)
);
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.site_name IS '门店名称。当前样本全部为同一门店,仅作冗余展示。 | 来源: siteName';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_name IS '球台名称或台号。如 A7、A11、B1 等。用于业务报表展示与人工识别。 | 来源: tableName';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_area_name IS '台区名称。观测枚举值包括 A区、B区、斯诺克区、麻将房。实际取值随门店台区配置变化。 | 来源: tableAreaName';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.order_pay_id IS '支付流水 ID。部分记录为 0,表示未在当前导出范围内关联到具体支付记录。真实含义为“指向支付记录表中的支付流水”。 | 来源: order_pay_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_option_price IS '商品规格价格,用于商品类促销分摊时使用。当前在团购券核销场景中全部为 0,仅作为结构预留。 | 来源: goodsOptionPrice';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_promotion_money IS '本次券使用中分摊到“商品”部分的促销金额。当前所有记录为 0,说明本门店的团购券未用于商品抵扣。 | 来源: goods_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_service_promotion_money IS '本次券使用中分摊到“台费服务费”部分的促销金额。当前样本全部为 0,结构上用于支持更细粒度的费用拆分。 | 来源: table_service_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_promotion_money IS '本次券使用中分摊到“助教服务”的促销金额。当前全部为 0,说明团购券尚未用于助教服务的抵扣。 | 来源: assistant_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_service_promotion_money IS '进一步细分助教服务对应的促销金额。当前为 0,仅预留结构以支持复杂场景。 | 来源: assistant_service_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.reward_promotion_money IS '本次促销中属于“奖励金、积分”等来源的促销金额分摊。当前为 0,预留用于积分或奖励金同时参与活动时的金额拆分。 | 来源: reward_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.recharge_promotion_money IS '来自“充值赠送”等储值优惠的促销金额分摊。当前为 0,预留用于将来区分“券优惠”和“充值赠送优惠”的场景。 | 来源: recharge_promotion_money';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.offer_type IS '优惠类型枚举。当前样本值全部为 1,表示本门店使用的团购券均为同一类型(例如“套餐券”)。其他取值可能对应满减、折扣、代金券等优惠类型,在本数据中未出现。 | 来源: offer_type';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_status IS '流水状态。观测值全部为 1。常规含义为:1 表示正常有效记录;其他值预留用于表示作废、撤销、未生效等状态。当前导出仅包含正常状态记录。 | 来源: ledger_status';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_id IS '执行本次券核销操作的操作员 ID。可与员工维度表对接,用于分析不同操作员的核销行为与绩效。 | 来源: operator_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_name IS '操作员名称及角色说明,例如“收银员:郑丽珊”。与 operator_id 冗余,对报表展示友好,但不参与模型关联。 | 来源: operator_name';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_user_id IS '营业员用户 ID。当前全部为 0,表示本门店在团购券场景未单独记录营业员信息。 | 来源: salesman_user_id | 角色: 外键';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_name IS '营业员姓名。当前为空字符串。结构上用于记录拉单或促销的业务员信息。 | 来源: salesman_name';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_role_id IS '营业员角色 ID。当前为 0,预留用于标识营业员在组织中的角色类型。 | 来源: salesman_role_id';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_org_id IS '营业员所属组织 ID。来源字段为 sales_man_org_id,DWD 层统一命名为 salesman_org_id。当前为 0,用于将来对接组织架构维度。 | 来源: sales_man_org_id';
-COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_group_name IS '团购项目的记账分组名称。当前全部为空,预留给将来按团购项目大类分组(例如“团购台费”“团购包厢”)使用。 | 来源: ledger_group_name';
--- dwd_platform_coupon_redemption
+COMMENT ON TABLE billiards_dwd.dwd_groupbuy_redemption_ex IS 'DWD 明细事实表(扩展字段表):dwd_groupbuy_redemption_ex。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029615941(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - siteName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - siteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A17(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - tableName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - tableAreaName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableAreaName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_pay_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.goods_option_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - goodsOptionPrice。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goodsOptionPrice。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - goods_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goods_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_service_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - table_service_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_service_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - assistant_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.assistant_service_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - assistant_service_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_service_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.reward_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - reward_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - reward_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.recharge_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - recharge_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - recharge_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.offer_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - offer_type。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - offer_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】group_buy_redemption_records - ledger_status。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - operator_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - operator_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - salesman_user_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - salesman_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - salesman_role_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_role_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - sales_man_org_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - sales_man_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - ledger_group_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_group_name。';
+
+
CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
platform_coupon_redemption_id BIGINT,
tenant_id BIGINT,
@@ -1452,28 +1726,30 @@ CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
consume_time TIMESTAMPTZ,
PRIMARY KEY (platform_coupon_redemption_id)
);
-COMMENT ON COLUMN dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.tenant_id IS '租户 ID,品牌级别标识。例如整套系统中的“朗朗桌球”品牌。与其他表的 tenant_id 一致,用于划分租户数据域。 | 来源: tenant_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于区分不同门店。siteProfile.id 与此字段相同,本表不再冗余门店快照。 | 来源: site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_code IS '第三方团购券券码,顾客出示的核销码。当前样本中全表唯一,可视为业务自然主键,用于验券、对账、查询。 | 来源: coupon_code';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_channel IS '券来源渠道枚举,表示第三方平台渠道编号。观测值:1,2。具体含义需结合系统配置,一般可理解为:1 表示平台渠道 1(主平台),2 表示平台渠道 2(其他入口或子平台)。 | 来源: coupon_channel';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_name IS '第三方团购券产品名称,例如“【全天可用】中八桌球一小时(A区)”“1小时中八台球【11月特惠】(A区)”等。用于报表展示和区分不同团购产品。 | 来源: coupon_name';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.sale_price IS '顾客在第三方平台实际支付的团购售价,例如 11.11、29.90、39.90 等。始终小于 coupon_money,体现“折后价”。 | 来源: sale_price';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_money IS '券面值或套餐价值,即系统认为该券可抵扣的金额,例如 48.00、58.00、68.00、96.00、116.00、288.00。与 coupon_name 有固定对应关系。 | 来源: coupon_money';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_free_time IS '券附带的赠送时长,单位:秒。当前样本全部为 0,表示无独立赠送时长。若未来有赠送时间型券,则该字段存储赠送的秒数。 | 来源: coupon_free_time';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.channel_deal_id IS '渠道侧团购商品 ID(第三方平台 dealId)。值域有限(约 9 个值),与 coupon_name 一一对应。用于对接第三方接口和按平台商品维度统计。 | 来源: channel_deal_id | 角色: - 或 外键(预留)';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.deal_id IS '平台/系统侧团购商品 ID。多数记录为非 0 整数,也有部分为 0。与 coupon_name 存在稳定对应关系,0 表示内部未配置或未同步。未来可作为内部团购商品维度外键。 | 来源: deal_id | 角色: 外键(预留)';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.group_package_id IS '内部“团购套餐”定义表主键 ID。当前样本中全部为 0,表示平台券尚未映射到自有团购套餐;从设计上是预留的外键字段。 | 来源: group_package_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.site_order_id IS '门店内部订单 ID。本次平台券核销所挂靠的店内订单号。用于与结账记录、台费流水、商品销售等事实表通过订单维度关联。 | 来源: site_order_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.table_id IS '使用团购券的球台 ID。与 dim_site_table.table_id 对应,用于统计每张球台的第三方平台引流情况。 | 来源: table_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.certificate_id IS '第三方平台侧券实例 ID(凭证 ID),通常为 16–19 位数字字符串。用于与外部平台对账与查询核销结果。存在重复值,不能单独作为唯一键。 | 来源: certificate_id';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.verify_id IS '第三方平台核销记录 ID。大部分记录为空,少量有值。存在时可用于精确反查平台侧核销记录。 | 来源: verify_id';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.use_status IS '券使用状态枚举。观测值:1、2。1 表示已使用/已核销(正常消耗);2 表示已退款/已撤销或使用后反冲的状态。是判断券生命周期状态的核心字段。 | 来源: use_status';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.is_delete IS '逻辑删除标志。0 表示未删除;1 表示已逻辑删除。与 use_status 独立:即便业务状态异常(如 use_status=2),也可能 is_delete 仍为 0 以保留记录。 | 来源: is_delete';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.create_time IS '系统记录创建时间,即核销记录写入本系统的时间。格式为 YYYY-MM-DD HH:MM:SS。通常与 consume_time 相差约 1 秒。 | 来源: create_time';
-COMMENT ON COLUMN dwd_platform_coupon_redemption.consume_time IS '券被核销/使用的业务时间,代表实际团购券使用发生的时间点。后续按核销日期统计核销量时以该字段为准。 | 来源: consume_time';
--- dwd_platform_coupon_redemption_Ex
+COMMENT ON TABLE billiards_dwd.dwd_platform_coupon_redemption IS 'DWD 明细事实表:dwd_platform_coupon_redemption。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929042218501(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - id。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - tenant_id。 【JSON字段】platform_coupon_redemption_records.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - site_id。 【JSON字段】platform_coupon_redemption_records.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_code IS '【说明】明细字段,用于记录事实取值。 【示例】0102701209726(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_code。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_code。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_channel IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_channel。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】【全天可用】中八桌球一小时(A区)(名称字段,用于展示与辅助识别)。 【ODS来源】platform_coupon_redemption_records - coupon_name。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.sale_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】29.9(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】platform_coupon_redemption_records - sale_price。 【JSON字段】platform_coupon_redemption_records.json - $ - sale_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】platform_coupon_redemption_records - coupon_money。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_free_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - coupon_free_time。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_free_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.channel_deal_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1128411555(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - channel_deal_id。 【JSON字段】platform_coupon_redemption_records.json - $ - channel_deal_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.deal_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1345108507(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - deal_id。 【JSON字段】platform_coupon_redemption_records.json - $ - deal_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.group_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - group_package_id。 【JSON字段】platform_coupon_redemption_records.json - $ - group_package_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.site_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929043037702(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - site_order_id。 【JSON字段】platform_coupon_redemption_records.json - $ - site_order_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793001904918661(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - table_id。 【JSON字段】platform_coupon_redemption_records.json - $ - table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.certificate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】5008024789379597447(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - certificate_id。 【JSON字段】platform_coupon_redemption_records.json - $ - certificate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.verify_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】7570689090418149418(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - verify_id。 【JSON字段】platform_coupon_redemption_records.json - $ - verify_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.use_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】platform_coupon_redemption_records - use_status。 【JSON字段】platform_coupon_redemption_records.json - $ - use_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】platform_coupon_redemption_records - is_delete。 【JSON字段】platform_coupon_redemption_records.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:41:03(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - create_time。 【JSON字段】platform_coupon_redemption_records.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.consume_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:41:04(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - consume_time。 【JSON字段】platform_coupon_redemption_records.json - $ - consume_time。';
+
+
CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
platform_coupon_redemption_id BIGINT,
coupon_cover VARCHAR(255),
@@ -1483,14 +1759,16 @@ CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
operator_name VARCHAR(50),
PRIMARY KEY (platform_coupon_redemption_id)
);
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_cover IS '券封面图片地址 URL,用于前端展示团购券图片。对经营分析和结算逻辑无影响。 | 来源: coupon_cover';
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_remark IS '券描述或备注信息,用于展示券规则、说明文字。未参与计算和关联逻辑。 | 来源: coupon_remark';
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.groupon_type IS '团购券类型枚举。当前样本全部为 1。推断含义:1 表示标准团购券,其他值预留为次卡、套餐券、权益券等类型。 | 来源: groupon_type';
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_id IS '执行验券操作的员工/收银员账号 ID。当前样本中多数为同一值。可与员工/账号维度表关联。 | 来源: operator_id | 角色: 外键';
-COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_name IS '操作员姓名或显示名,例如“收银员:郑丽珊”。是 operator_id 的冗余展示字段,用于报表展示。 | 来源: operator_name';
--- dwd_recharge_order
+COMMENT ON TABLE billiards_dwd.dwd_platform_coupon_redemption_ex IS 'DWD 明细事实表(扩展字段表):dwd_platform_coupon_redemption_ex。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.platform_coupon_redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929042218501(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - id。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.coupon_cover IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_cover。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_cover。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.coupon_remark IS '【说明】明细字段,用于记录事实取值。 【示例】617547ec-9697-4f58-a700-b30a49e88904||CgYIASAHKAESLgos9ZhHDryhHb0z3RpdBZ0dVoaQbkldBcx/XTXPV8Te+9SEqYOa7aDp8nbKOpsaAA==(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_remark。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_remark。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.groupon_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - groupon_type。 【JSON字段】platform_coupon_redemption_records.json - $ - groupon_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - operator_id。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】platform_coupon_redemption_records - operator_name。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_name。';
+
+
CREATE TABLE IF NOT EXISTS dwd_recharge_order (
recharge_order_id BIGINT,
tenant_id BIGINT,
@@ -1513,27 +1791,29 @@ CREATE TABLE IF NOT EXISTS dwd_recharge_order (
pay_time TIMESTAMPTZ,
PRIMARY KEY (recharge_order_id)
);
-COMMENT ON COLUMN dwd_recharge_order.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_recharge_order.tenant_id IS '租户/品牌 ID;与其他 JSON 中 tenantId 含义一致。 | 来源: tenantId | 角色: 外键(dim_tenant)';
-COMMENT ON COLUMN dwd_recharge_order.site_id IS '门店 ID;与 siteProfile.id 一致,用于关联门店维度。 | 来源: siteId | 角色: 外键(dim_site)';
-COMMENT ON COLUMN dwd_recharge_order.member_id IS '会员 ID;对应会员档案中的 tenantMemberInfos.id。标识给哪个会员充值。 | 来源: memberId | 角色: 外键(dim_member)';
-COMMENT ON COLUMN dwd_recharge_order.member_name_snapshot IS '会员姓名/昵称快照,可能是名称或手机号字符串。 | 来源: memberName';
-COMMENT ON COLUMN dwd_recharge_order.member_phone_snapshot IS '会员手机号快照。 | 来源: memberPhone';
-COMMENT ON COLUMN dwd_recharge_order.tenant_member_card_id IS '会员卡实例 ID(某张具体卡);可关联 dim_member_card_account。 | 来源: tenantMemberCardId | 角色: 外键(dim_member_card_account)';
-COMMENT ON COLUMN dwd_recharge_order.member_card_type_name IS '会员卡类型名称;当前样例主要有:“储值卡”、“月卡”。 | 来源: memberCardTypeName';
-COMMENT ON COLUMN dwd_recharge_order.settle_relate_id IS '结算关联 ID;用于与支付记录等跨表关联(类似业务单 ID)。 | 来源: settleRelateId | 角色: 外键(与支付/结算域软关联)';
-COMMENT ON COLUMN dwd_recharge_order.settle_type IS '结算类型枚举:5=“充值订单”(正常充值);7=“充值撤销”(冲销记录)。 | 来源: settleType';
-COMMENT ON COLUMN dwd_recharge_order.settle_name IS '结算类型名称:"充值订单"、"充值撤销";前端展示用。 | 来源: settleName';
-COMMENT ON COLUMN dwd_recharge_order.is_first IS '是否首充标记。取值:1 或 2。理论含义类似“是否首充”,但 1/2 的精确定义需系统字典确认。 | 来源: isFirst';
-COMMENT ON COLUMN dwd_recharge_order.pay_amount IS '本条记录的充值金额(可为正/负):正数=实际充值金额;负数=撤销流水金额(settleType=7)。 | 来源: payAmount';
-COMMENT ON COLUMN dwd_recharge_order.refund_amount IS '对该充值订单的退款金额(通常为正数);原始充值单上为已退款金额,对应会有一条负数的“充值撤销”记录。 | 来源: refundAmount';
-COMMENT ON COLUMN dwd_recharge_order.point_amount IS '计入会员账户的储值/积分金额;多数情况下等于 pay_amount 的绝对值;撤销记录一般为 0。 | 来源: pointAmount';
-COMMENT ON COLUMN dwd_recharge_order.cash_amount IS '现金收款金额;样本中少数为 3000/5000,其余为 0。 | 来源: cashAmount';
-COMMENT ON COLUMN dwd_recharge_order.payment_method IS '支付方式编码。样本取值:1、2、4;具体对应渠道(现金/微信/支付宝/银行卡等)需系统“支付方式字典”确认。 | 来源: paymentMethod';
-COMMENT ON COLUMN dwd_recharge_order.create_time IS '充值记录创建时间(收银完成时间);用于时间分区、统计。 | 来源: createTime';
-COMMENT ON COLUMN dwd_recharge_order.pay_time IS '支付完成时间;通常与 create_time 接近或相同。 | 来源: payTime';
--- dwd_recharge_order_Ex
+COMMENT ON TABLE billiards_dwd.dwd_recharge_order IS 'DWD 明细事实表:dwd_recharge_order。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.recharge_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - id。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tenantid。 【JSON字段】recharge_settlements.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - siteid。 【JSON字段】recharge_settlements.json - $ - siteid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - memberid。 【JSON字段】recharge_settlements.json - $ - memberid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - membername。 【JSON字段】recharge_settlements.json - $ - membername。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_phone_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - memberphone。 【JSON字段】recharge_settlements.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.tenant_member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tenantmembercardid。 【JSON字段】recharge_settlements.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - membercardtypename。 【JSON字段】recharge_settlements.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - settlerelateid。 【JSON字段】recharge_settlements.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_type IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - settletype。 【JSON字段】recharge_settlements.json - $ - settletype。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - settlename。 【JSON字段】recharge_settlements.json - $ - settlename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.is_first IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isfirst。 【JSON字段】recharge_settlements.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - payamount。 【JSON字段】recharge_settlements.json - $ - payamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - refundamount。 【JSON字段】recharge_settlements.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.point_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointamount。 【JSON字段】recharge_settlements.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.cash_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - cashamount。 【JSON字段】recharge_settlements.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - paymentmethod。 【JSON字段】recharge_settlements.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - createtime。 【JSON字段】recharge_settlements.json - $ - createtime。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - paytime。 【JSON字段】recharge_settlements.json - $ - paytime。';
+
+
CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
recharge_order_id BIGINT,
site_name_snapshot TEXT,
@@ -1580,51 +1860,53 @@ CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
revoke_time TIMESTAMPTZ,
PRIMARY KEY (recharge_order_id)
);
-COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
-COMMENT ON COLUMN dwd_recharge_order_Ex.site_name_snapshot IS '门店名称快照,如“朗朗桌球”;仅用于展示,门店改名后本字段不变。 | 来源: siteName';
-COMMENT ON COLUMN dwd_recharge_order_Ex.settle_status IS '结算状态;当前数据全部为 2,推测 2=已完成。其它状态未出现在样本中。 | 来源: settleStatus';
-COMMENT ON COLUMN dwd_recharge_order_Ex.is_bind_member IS '是否绑定为会员/其他绑定标记;当前所有记录为 False,而又都有 memberId,实际业务含义不清。 | 来源: isBindMember';
-COMMENT ON COLUMN dwd_recharge_order_Ex.is_activity IS '是否关联营销活动;当前全部为 False,表示样本周期内充值未绑定活动。 | 来源: isActivity';
-COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_coupon IS '本次充值是否使用优惠券;当前样本全部为 False。结构上预留“充值用券”的能力。 | 来源: isUseCoupon';
-COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_discount IS '是否使用折扣(如充值折扣);样本中全为 False。 | 来源: isUseDiscount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.can_be_revoked IS '当前记录是否仍可撤销;样本中全为 False(导出时均不可撤销)。 | 来源: canBeRevoked';
-COMMENT ON COLUMN dwd_recharge_order_Ex.online_amount IS '线上支付金额(如微信、支付宝等);当前样本为 0,但字段为支付渠道拆分预留。 | 来源: onlineAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.balance_amount IS '从账户余额中支付的金额;充值场景通常为 0(用余额充值没有实际意义)。 | 来源: balanceAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.card_amount IS '从其他储值卡或某种卡余额支付的金额;当前样本全为 0。 | 来源: cardAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_amount IS '使用券直接支付的金额(如储值券);当前样本为 0。 | 来源: couponAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_card_amount IS '充值到卡上的金额(与 point_amount 区分不同资金属性);样本为 0,结构预留。 | 来源: rechargeCardAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.gift_card_amount IS '赠送卡金额(如买 1000 送 100 的赠送部分);当前样本为 0。 | 来源: giftCardAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.prepay_money IS '预付款金额(订金);当前样本为 0,充值未启用此场景。 | 来源: prepayMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.consume_money IS '消费总金额;在充值文件中全部为 0,实际用于消费场景(台费/商品)的结算模型复用字段。 | 来源: consumeMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.goods_money IS '商品消费金额(充值记录中为 0)。 | 来源: goodsMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.real_goods_money IS '实际应计商品金额(扣除折扣后);充值记录中为 0。 | 来源: realGoodsMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.table_charge_money IS '台费金额;充值记录中为 0,来自通用结算模型。 | 来源: tableChargeMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.service_money IS '服务项目金额(如助教、其他服务);充值中为 0。 | 来源: serviceMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.activity_discount IS '营销活动折扣金额;当前样本为 0。 | 来源: activityDiscount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.all_coupon_discount IS '各类优惠券、团购券综合折扣金额;样本为 0。 | 来源: allCouponDiscount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.goods_promotion_money IS '商品促销优惠金额;样本为 0。 | 来源: goodsPromotionMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_promotion_money IS '助教相关促销优惠金额;样本为 0。 | 来源: assistantPromotionMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_pd_money IS '助教配单金额/相关费用;样本为 0。 | 来源: assistantPdMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_cx_money IS '助教冲销/促销相关金额;样本为 0。 | 来源: assistantCxMoney';
-COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_manual_discount IS '助教手工减免金额;样本为 0。 | 来源: assistantManualDiscount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_sale_amount IS '券/套餐销售金额(售卖券时使用);充值场景中为 0。 | 来源: couponSaleAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.member_discount_amount IS '因会员折扣产生的优惠金额;在充值样本中为 0。 | 来源: memberDiscountAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_price IS '积分抵扣产生的价差(价格部分);样本为 0。 | 来源: pointDiscountPrice';
-COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_cost IS '积分抵扣对应的成本金额;样本为 0。 | 来源: pointDiscountCost';
-COMMENT ON COLUMN dwd_recharge_order_Ex.adjust_amount IS '手工调整金额(非抹零);样本为 0。 | 来源: adjustAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.rounding_amount IS '抹零金额(四舍五入产生的差额);样本为 0。 | 来源: roundingAmount';
-COMMENT ON COLUMN dwd_recharge_order_Ex.operator_id IS '操作该笔充值的收银员/员工 ID。 | 来源: operatorId | 角色: 外键(将来可关联 dim_staff)';
-COMMENT ON COLUMN dwd_recharge_order_Ex.operator_name_snapshot IS '操作员姓名快照,便于直接阅读;与 operator_id 对应。 | 来源: operatorName';
-COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_user_id IS '营业员用户 ID;当前样本全部为 0。 | 来源: salesManUserId | 角色: 外键(潜在 dim_staff)';
-COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_name IS '营业员/销售员姓名;样本为空字符串。 | 来源: salesManName';
-COMMENT ON COLUMN dwd_recharge_order_Ex.order_remark IS '充值订单备注,如手工说明;当前样本为空。 | 来源: orderRemark';
-COMMENT ON COLUMN dwd_recharge_order_Ex.table_id IS '台桌 ID;充值场景下全部是 0,表示该订单不挂具体球台。 | 来源: tableId';
-COMMENT ON COLUMN dwd_recharge_order_Ex.serial_number IS '流水/小票序号;当前样本全部为 0,本门店未启用。 | 来源: serialNumber';
-COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_id IS '撤销相关订单 ID(被撤销原单或撤销单指针);样本中存在值但逻辑未完全启用。 | 来源: revokeOrderId';
-COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_name IS '撤销单名称/说明;样本全为空。 | 来源: revokeOrderName';
-COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_time IS '撤销时间;当前样本为空,撤销信息主要通过负数流水与 refund_amount 表达。 | 来源: revokeTime';
--- dwd_payment
+COMMENT ON TABLE billiards_dwd.dwd_recharge_order_ex IS 'DWD 明细事实表(扩展字段表):dwd_recharge_order_ex。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.recharge_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - id。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.site_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - sitename。 【JSON字段】recharge_settlements.json - $ - sitename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.settle_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】NULL(状态枚举字段,用于标识业务状态)。 【ODS来源】recharge_settlements - settlestatus。 【JSON字段】recharge_settlements.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_bind_member IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isbindmember(派生:BOOLEAN(isbindmember))。 【JSON字段】recharge_settlements.json - $ - isbindmember(派生:BOOLEAN(isbindmember))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_activity IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isactivity(派生:BOOLEAN(isactivity))。 【JSON字段】recharge_settlements.json - $ - isactivity(派生:BOOLEAN(isactivity))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_use_coupon IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isusecoupon(派生:BOOLEAN(isusecoupon))。 【JSON字段】recharge_settlements.json - $ - isusecoupon(派生:BOOLEAN(isusecoupon))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_use_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - isusediscount(派生:BOOLEAN(isusediscount))。 【JSON字段】recharge_settlements.json - $ - isusediscount(派生:BOOLEAN(isusediscount))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.can_be_revoked IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - canberevoked(派生:BOOLEAN(canberevoked))。 【JSON字段】recharge_settlements.json - $ - canberevoked(派生:BOOLEAN(canberevoked))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.online_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - onlineamount。 【JSON字段】recharge_settlements.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.balance_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - balanceamount。 【JSON字段】recharge_settlements.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - cardamount。 【JSON字段】recharge_settlements.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.coupon_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - couponamount。 【JSON字段】recharge_settlements.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.recharge_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - rechargecardamount。 【JSON字段】recharge_settlements.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.gift_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - giftcardamount。 【JSON字段】recharge_settlements.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.prepay_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - prepaymoney。 【JSON字段】recharge_settlements.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.consume_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - consumemoney。 【JSON字段】recharge_settlements.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - goodsmoney。 【JSON字段】recharge_settlements.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - realgoodsmoney。 【JSON字段】recharge_settlements.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - tablechargemoney。 【JSON字段】recharge_settlements.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - servicemoney。 【JSON字段】recharge_settlements.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.activity_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - activitydiscount。 【JSON字段】recharge_settlements.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.all_coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - allcoupondiscount。 【JSON字段】recharge_settlements.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - goodspromotionmoney。 【JSON字段】recharge_settlements.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantpromotionmoney。 【JSON字段】recharge_settlements.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_pd_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantpdmoney。 【JSON字段】recharge_settlements.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_cx_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantcxmoney。 【JSON字段】recharge_settlements.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_manual_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - assistantmanualdiscount。 【JSON字段】recharge_settlements.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.coupon_sale_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - couponsaleamount。 【JSON字段】recharge_settlements.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - memberdiscountamount。 【JSON字段】recharge_settlements.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.point_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointdiscountprice。 【JSON字段】recharge_settlements.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.point_discount_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointdiscountcost。 【JSON字段】recharge_settlements.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - adjustamount。 【JSON字段】recharge_settlements.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.rounding_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - roundingamount。 【JSON字段】recharge_settlements.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - operatorid。 【JSON字段】recharge_settlements.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.operator_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - operatorname。 【JSON字段】recharge_settlements.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - salesmanuserid。 【JSON字段】recharge_settlements.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - salesmanname。 【JSON字段】recharge_settlements.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.order_remark IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - orderremark。 【JSON字段】recharge_settlements.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tableid。 【JSON字段】recharge_settlements.json - $ - tableid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - serialnumber。 【JSON字段】recharge_settlements.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - revokeorderid。 【JSON字段】recharge_settlements.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_order_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - revokeordername。 【JSON字段】recharge_settlements.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - revoketime。 【JSON字段】recharge_settlements.json - $ - revoketime。';
+
+
CREATE TABLE IF NOT EXISTS dwd_payment (
payment_id BIGINT,
site_id BIGINT,
@@ -1639,19 +1921,21 @@ CREATE TABLE IF NOT EXISTS dwd_payment (
pay_date DATE,
PRIMARY KEY (payment_id)
);
-COMMENT ON COLUMN dwd_payment.payment_id IS '支付流水主键ID。与源系统 id 一致。每条支付流水唯一标识一条支付行为(包括金额为 0 的记录)。 | 来源: payment_transactions.id | 角色: 主键';
-COMMENT ON COLUMN dwd_payment.site_id IS '门店ID。当前样本中全部为同一门店 2790685415443269。在数仓中外键关联 dim_site.site_id。 | 来源: payment_transactions.site_id | 角色: 外键';
-COMMENT ON COLUMN dwd_payment.relate_type IS '业务关联类型枚举,用来区分这条支付流水对应哪一类业务单据:• 2:结账单支付,对应结账记录 settlement_records 中的结账单;• 5:会员卡充值/账户变动类支付,对应会员余额/充值业务单号,在会员余额变更或充值结算中复用;• 1:其他业务类型,目前样本中仅有 1 条记录,具体业务含义待业务侧补充。 | 来源: payment_transactions.relate_type | 角色: −';
-COMMENT ON COLUMN dwd_payment.relate_id IS '关联业务记录ID,配合 relate_type 使用,是一个“多态外键”:• 当 relate_type = 2 时:relate_id = settlement_records.settleList.id(结账记录主键,对应 dwd_settlement_head_di.order_settle_id);• 当 relate_type = 5 时:relate_id = 会员卡余额变动/充值业务单号,在会员余额变更流水中同名字段使用;• 当 relate_type = 1 时:关联具体业务尚未确认,仅可视为预留类型。 | 来源: payment_transactions.relate_id | 角色: 外键(多业务类型)';
-COMMENT ON COLUMN dwd_payment.pay_amount IS '本次支付金额,单位元。为收入类字段,当前样本全部为非负数:• 正数:实际通过该支付方式收取的金额;• 0:仍生成支付流水,但实收金额为 0(例如整单由会员优惠、团购券、余额等抵扣),当前样本中有 140 条记录金额为 0。 | 来源: payment_transactions.pay_amount | 角色: −';
-COMMENT ON COLUMN dwd_payment.pay_status IS '支付状态枚举。当前样本中仅出现:• 2:支付成功。其它可能的状态(未支付、支付中、失败、已退款等)在本次导出中未出现,需以后按系统支付状态配置补充。由于本 JSON 仅导出成功记录,可以视作“成功支付流水视图”。 | 来源: payment_transactions.pay_status | 角色: −';
-COMMENT ON COLUMN dwd_payment.payment_method IS '支付方式枚举。当前样本中出现的取值:• 2:共 140 条记录;• 4:共 60 条记录。具体取值与“支付方式配置表”对应,例如可能代表现金、扫码支付、银行卡等。由于配置表未导出,在数仓中应作为枚举码字段,通过后续 dim_payment_method 进行解码。不要在数仓层擅自写死“2=微信、4=支付宝”等含义。 | 来源: payment_transactions.payment_method | 角色: 外键(预期关联支付方式维度)';
-COMMENT ON COLUMN dwd_payment.online_pay_channel IS '线上支付通道枚举。用于进一步细分线上渠道,例如:• 0:无线上通道/线下,或未区分具体线上通道(当前样本全部为 0);• 1:微信(推测,未在样本中出现);• 2:支付宝(推测,未在样本中出现)。目前门店在当前时间段内尚未使用该字段进行实际区分,业务含义需结合正式配置确认。 | 来源: payment_transactions.online_pay_channel | 角色: −';
-COMMENT ON COLUMN dwd_payment.create_time IS '支付流水创建时间,格式 YYYY-MM-DD HH:MM:SS。通常是发起支付请求的时间。当前样本中 create_time 与 pay_time 多数相同,但模型上允许两者不同(例如异步支付)。 | 来源: payment_transactions.create_time | 角色: −';
-COMMENT ON COLUMN dwd_payment.pay_time IS '支付完成时间(支付成功时间戳),格式 YYYY-MM-DD HH:MM:SS。用于统计资金实际入账时间,以及与结账时间进行对齐分析。 | 来源: payment_transactions.pay_time | 角色: −';
-COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_time 截取 YYYY-MM-DD 得到。例如 pay_time = ''2025-11-09 23:35:57'' 时,pay_date = ''2025-11-09''。用于 DWD 表按天分区和日粒度汇总。 | 来源: 由 payment_transactions.pay_time 派生 | 角色: −';
--- dwd_refund
+COMMENT ON TABLE billiards_dwd.dwd_payment IS 'DWD 明细事实表:dwd_payment。ODS 来源表:billiards_ods.payment_transactions(对应 JSON:payment_transactions.json;分析:payment_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.payment_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924026486597(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - id。 【JSON字段】payment_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - site_id。 【JSON字段】payment_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.relate_type IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - relate_type。 【JSON字段】payment_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - relate_id。 【JSON字段】payment_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】10.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】payment_transactions - pay_amount。 【JSON字段】payment_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】payment_transactions - pay_status。 【JSON字段】payment_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】4(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - payment_method。 【JSON字段】payment_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.online_pay_channel IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - online_pay_channel。 【JSON字段】payment_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - create_time。 【JSON字段】payment_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - pay_time。 【JSON字段】payment_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_date IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - pay_time(派生:DATE(pay_time))。 【JSON字段】payment_transactions.json - $ - pay_time(派生:DATE(pay_time))。';
+
+
CREATE TABLE IF NOT EXISTS dwd_refund (
refund_id BIGINT,
tenant_id BIGINT,
@@ -1667,18 +1951,20 @@ COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_ti
member_card_id BIGINT,
PRIMARY KEY (refund_id)
);
- COMMENT ON COLUMN dwd_refund.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型) | 来源: id | 角色: 主键';
- COMMENT ON COLUMN dwd_refund.tenant_id IS '租户/品牌 ID,标识所属商户。与其他表中的 tenant_id 一致。 | 来源: tenant_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于分门店分析。 | 来源: site_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund.relate_type IS '业务类型枚举,指示本退款对应哪类业务主单:当前样本值 {2, 5}:2=消费/结账类业务;5=充值/储值类业务(具体定义以业务字典为准)。与 relate_id 组合使用。 | 来源: relate_type';
- COMMENT ON COLUMN dwd_refund.relate_id IS '关联的业务主键 ID,含义依赖 relate_type:relate_type=2 时通常指结账主单 ID;relate_type=5 时通常指充值/储值业务单 ID。同一个 relate_id 可能有多笔退款(分批退款)。 | 来源: relate_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund.pay_amount IS '本次退款的资金金额,统一为负数。绝对值即退款金额,例如 -5000.00 表示退款 5000 元。 | 来源: pay_amount';
- COMMENT ON COLUMN dwd_refund.channel_fee IS '第三方支付渠道对本次退款收取的手续费。当前样本为 0.00,用于通道成本核算。 | 来源: channel_fee';
- COMMENT ON COLUMN dwd_refund.pay_time IS '退款在支付渠道/系统中发生的时间(退款完成时间),用于对账及按时间统计。 | 来源: pay_time';
- COMMENT ON COLUMN dwd_refund.create_time IS '本条退款流水在系统内创建时间,用于区分记录生成时间与渠道时间。 | 来源: create_time';
- COMMENT ON COLUMN dwd_refund.payment_method IS '支付方式枚举,指本次退款对应的原支付方式(如通道)。样本出现值 4,支付记录中有 {2,4},具体含义需参照支付方式配置表。 | 来源: payment_method';
- COMMENT ON COLUMN dwd_refund.member_id IS '关联的会员 ID,对应会员档案表主键。样本为 0,表示未绑定会员。 | 来源: member_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund.member_card_id IS '关联的会员卡账户 ID,对应会员卡账户/储值卡维度主键。样本为 0,当前没有“退到会员卡”的记录。 | 来源: member_card_id | 角色: 外键';
+
+COMMENT ON TABLE billiards_dwd.dwd_refund IS 'DWD 明细事实表:dwd_refund。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.refund_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955202296416389(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - id。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - tenant_id。 【JSON字段】refund_transactions.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - site_id。 【JSON字段】refund_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.relate_type IS '【说明】明细字段,用于记录事实取值。 【示例】5(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - relate_type。 【JSON字段】refund_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955078219057349(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - relate_id。 【JSON字段】refund_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】-5000.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - pay_amount。 【JSON字段】refund_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.channel_fee IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - channel_fee。 【JSON字段】refund_transactions.json - $ - channel_fee。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:27:16(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】refund_transactions - pay_time。 【JSON字段】refund_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:27:16(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】refund_transactions - create_time。 【JSON字段】refund_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】4(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - payment_method。 【JSON字段】refund_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - member_id。 【JSON字段】refund_transactions.json - $ - member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - member_card_id。 【JSON字段】refund_transactions.json - $ - member_card_id。';
CREATE TABLE IF NOT EXISTS dwd_refund_Ex (
@@ -1704,23 +1990,27 @@ COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_ti
channel_pay_no VARCHAR(128),
PRIMARY KEY (refund_id)
);
- COMMENT ON COLUMN dwd_refund_Ex.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。 | 来源: id | 角色: 主键';
- COMMENT ON COLUMN dwd_refund_Ex.tenant_name IS '租户名称,例如“朗朗桌球”。与租户维度中的名称冗余。 | 来源: tenantName';
- COMMENT ON COLUMN dwd_refund_Ex.pay_sn IS '支付流水内部序号。退款记录中样本全部为 0,未看到实际使用场景,含义未说明。 | 来源: pay_sn';
- COMMENT ON COLUMN dwd_refund_Ex.refund_amount IS '本次退款金额(正数)设计字段,样本为 0.00,实际使用 pay_amount。 | 来源: refund_amount';
- COMMENT ON COLUMN dwd_refund_Ex.round_amount IS '退款过程中的舍入/抹零金额。 | 来源: round_amount';
- COMMENT ON COLUMN dwd_refund_Ex.balance_frozen_amount IS '与会员余额相关的冻结金额,样本为 0。 | 来源: balance_frozen_amount';
- COMMENT ON COLUMN dwd_refund_Ex.card_frozen_amount IS '与某张会员卡余额相关的冻结金额,样本为 0。 | 来源: card_frozen_amount';
- COMMENT ON COLUMN dwd_refund_Ex.pay_status IS '退款状态枚举。样本中全部为 2(成功/已完成)。 | 来源: pay_status';
- COMMENT ON COLUMN dwd_refund_Ex.action_type IS '资金动作类型枚举。样本全部为 2(退款)。 | 来源: action_type';
- COMMENT ON COLUMN dwd_refund_Ex.is_revoke IS '是否为撤销型退款:0=正常退款;1=撤销原支付。 | 来源: is_revoke';
- COMMENT ON COLUMN dwd_refund_Ex.is_delete IS '逻辑删除标志:0=未删除;1=已逻辑删除。 | 来源: is_delete';
- COMMENT ON COLUMN dwd_refund_Ex.check_status IS '审核状态。样本全部为 1(已审核/通过)。 | 来源: check_status';
- COMMENT ON COLUMN dwd_refund_Ex.online_pay_channel IS '线上支付渠道枚举。样本中全部为 0(线下或默认)。 | 来源: online_pay_channel';
- COMMENT ON COLUMN dwd_refund_Ex.online_pay_type IS '在线退款类型。样本全部为 0(原路退回)。 | 来源: online_pay_type';
- COMMENT ON COLUMN dwd_refund_Ex.pay_terminal IS '退款终端类型。样本全部为 1(前台收银端)。 | 来源: pay_terminal';
- COMMENT ON COLUMN dwd_refund_Ex.pay_config_id IS '支付配置 ID,例如某个具体支付通道(微信商户号、银联通道等)的配置主键。样本全部为 0。 | 来源: pay_config_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund_Ex.cashier_point_id IS '收银点编号,例如前台1、前台2、自助机等。样本全部为 0。 | 来源: cashier_point_id';
- COMMENT ON COLUMN dwd_refund_Ex.operator_id IS '执行退款操作的操作员 ID。样本全部为 0。 | 来源: operator_id | 角色: 外键';
- COMMENT ON COLUMN dwd_refund_Ex.channel_payer_id IS '支付渠道侧的付款人标识,如 openid、银行卡号掩码等。样本全部为空字符串。 | 来源: channel_payer_id';
- COMMENT ON COLUMN dwd_refund_Ex.channel_pay_no IS '第三方支付平台交易号(如微信支付单号、支付宝交易号等)。当前样本全部为空。 | 来源: channel_pay_no';
+
+COMMENT ON TABLE billiards_dwd.dwd_refund_ex IS 'DWD 明细事实表(扩展字段表):dwd_refund_ex。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.refund_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955202296416389(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - id。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.tenant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】refund_transactions - tenantName。 【JSON字段】refund_transactions.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_sn IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - pay_sn。 【JSON字段】refund_transactions.json - $ - pay_sn。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - refund_amount。 【JSON字段】refund_transactions.json - $ - refund_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.round_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - round_amount。 【JSON字段】refund_transactions.json - $ - round_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.balance_frozen_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - balance_frozen_amount。 【JSON字段】refund_transactions.json - $ - balance_frozen_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.card_frozen_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - card_frozen_amount。 【JSON字段】refund_transactions.json - $ - card_frozen_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】refund_transactions - pay_status。 【JSON字段】refund_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.action_type IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - action_type。 【JSON字段】refund_transactions.json - $ - action_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.is_revoke IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】refund_transactions - is_revoke。 【JSON字段】refund_transactions.json - $ - is_revoke。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】refund_transactions - is_delete。 【JSON字段】refund_transactions.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.check_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】refund_transactions - check_status。 【JSON字段】refund_transactions.json - $ - check_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.online_pay_channel IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - online_pay_channel。 【JSON字段】refund_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.online_pay_type IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - online_pay_type。 【JSON字段】refund_transactions.json - $ - online_pay_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_terminal IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - pay_terminal。 【JSON字段】refund_transactions.json - $ - pay_terminal。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_config_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - pay_config_id。 【JSON字段】refund_transactions.json - $ - pay_config_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.cashier_point_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - cashier_point_id。 【JSON字段】refund_transactions.json - $ - cashier_point_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - operator_id。 【JSON字段】refund_transactions.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.channel_payer_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - channel_payer_id。 【JSON字段】refund_transactions.json - $ - channel_payer_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.channel_pay_no IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - channel_pay_no。 【JSON字段】refund_transactions.json - $ - channel_pay_no。';
+
+
diff --git a/etl_billiards/database/schema_dws.sql b/etl_billiards/database/schema_dws.sql
new file mode 100644
index 0000000..03e1a86
--- /dev/null
+++ b/etl_billiards/database/schema_dws.sql
@@ -0,0 +1,50 @@
+-- DWS schema for aggregated / serving tables.
+CREATE SCHEMA IF NOT EXISTS billiards_dws;
+
+CREATE TABLE IF NOT EXISTS billiards_dws.dws_order_summary (
+ site_id BIGINT NOT NULL,
+ order_settle_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_date DATE,
+ tenant_id BIGINT,
+ member_id BIGINT,
+ member_flag BOOLEAN,
+ recharge_order_flag BOOLEAN,
+ item_count INT,
+ total_item_quantity NUMERIC,
+ table_fee_amount NUMERIC,
+ assistant_service_amount NUMERIC,
+ goods_amount NUMERIC,
+ group_amount NUMERIC,
+ total_coupon_deduction NUMERIC,
+ member_discount_amount NUMERIC,
+ manual_discount_amount NUMERIC,
+ order_original_amount NUMERIC,
+ order_final_amount NUMERIC,
+ stored_card_deduct NUMERIC,
+ external_paid_amount NUMERIC,
+ total_paid_amount NUMERIC,
+ book_table_flow NUMERIC,
+ book_assistant_flow NUMERIC,
+ book_goods_flow NUMERIC,
+ book_group_flow NUMERIC,
+ book_order_flow NUMERIC,
+ order_effective_consume_cash NUMERIC,
+ order_effective_recharge_cash NUMERIC,
+ order_effective_flow NUMERIC,
+ refund_amount NUMERIC,
+ net_income NUMERIC,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, order_settle_id)
+);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_order_date
+ ON billiards_dws.dws_order_summary (order_date);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_tenant_date
+ ON billiards_dws.dws_order_summary (tenant_id, order_date);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_member_date
+ ON billiards_dws.dws_order_summary (member_id, order_date);
+
diff --git a/etl_billiards/database/schema_etl_admin.sql b/etl_billiards/database/schema_etl_admin.sql
new file mode 100644
index 0000000..de98d86
--- /dev/null
+++ b/etl_billiards/database/schema_etl_admin.sql
@@ -0,0 +1,105 @@
+-- 文件说明:etl_admin 调度元数据 DDL(独立文件,便于初始化任务单独执行)。
+-- 包含任务注册表、游标表、运行记录表;字段注释使用中文。
+
+CREATE SCHEMA IF NOT EXISTS etl_admin;
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_task (
+ task_id BIGSERIAL PRIMARY KEY,
+ task_code TEXT NOT NULL,
+ store_id BIGINT NOT NULL,
+ enabled BOOLEAN DEFAULT TRUE,
+ cursor_field TEXT,
+ window_minutes_default INT DEFAULT 30,
+ overlap_seconds INT DEFAULT 120,
+ page_size INT DEFAULT 200,
+ retry_max INT DEFAULT 3,
+ params JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_code, store_id)
+);
+COMMENT ON TABLE etl_admin.etl_task IS '任务注册表:调度依据的任务清单(与 task_registry 中的任务码对应)。';
+COMMENT ON COLUMN etl_admin.etl_task.task_code IS '任务编码,需与代码中的任务码一致。';
+COMMENT ON COLUMN etl_admin.etl_task.store_id IS '门店/租户粒度,区分多门店执行。';
+COMMENT ON COLUMN etl_admin.etl_task.enabled IS '是否启用此任务。';
+COMMENT ON COLUMN etl_admin.etl_task.cursor_field IS '增量游标字段名(可选)。';
+COMMENT ON COLUMN etl_admin.etl_task.window_minutes_default IS '默认时间窗口(分钟)。';
+COMMENT ON COLUMN etl_admin.etl_task.overlap_seconds IS '窗口重叠秒数,用于防止遗漏。';
+COMMENT ON COLUMN etl_admin.etl_task.page_size IS '默认分页大小。';
+COMMENT ON COLUMN etl_admin.etl_task.retry_max IS 'API重试次数上限。';
+COMMENT ON COLUMN etl_admin.etl_task.params IS '任务级自定义参数 JSON。';
+COMMENT ON COLUMN etl_admin.etl_task.created_at IS '创建时间。';
+COMMENT ON COLUMN etl_admin.etl_task.updated_at IS '更新时间。';
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_cursor (
+ cursor_id BIGSERIAL PRIMARY KEY,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ last_start TIMESTAMPTZ,
+ last_end TIMESTAMPTZ,
+ last_id BIGINT,
+ last_run_id BIGINT,
+ extra JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_id, store_id)
+);
+COMMENT ON TABLE etl_admin.etl_cursor IS '任务游标表:记录每个任务/门店的增量窗口及最后 run。';
+COMMENT ON COLUMN etl_admin.etl_cursor.task_id IS '关联 etl_task.task_id。';
+COMMENT ON COLUMN etl_admin.etl_cursor.store_id IS '门店/租户粒度。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_start IS '上次窗口开始时间(含重叠偏移)。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_end IS '上次窗口结束时间。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_id IS '上次处理的最大主键/游标值(可选)。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_run_id IS '上次运行ID,对应 etl_run.run_id。';
+COMMENT ON COLUMN etl_admin.etl_cursor.extra IS '附加游标信息 JSON。';
+COMMENT ON COLUMN etl_admin.etl_cursor.created_at IS '创建时间。';
+COMMENT ON COLUMN etl_admin.etl_cursor.updated_at IS '更新时间。';
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_run (
+ run_id BIGSERIAL PRIMARY KEY,
+ run_uuid TEXT NOT NULL,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ status TEXT NOT NULL,
+ started_at TIMESTAMPTZ DEFAULT now(),
+ ended_at TIMESTAMPTZ,
+ window_start TIMESTAMPTZ,
+ window_end TIMESTAMPTZ,
+ window_minutes INT,
+ overlap_seconds INT,
+ fetched_count INT DEFAULT 0,
+ loaded_count INT DEFAULT 0,
+ updated_count INT DEFAULT 0,
+ skipped_count INT DEFAULT 0,
+ error_count INT DEFAULT 0,
+ unknown_fields INT DEFAULT 0,
+ export_dir TEXT,
+ log_path TEXT,
+ request_params JSONB DEFAULT '{}'::jsonb,
+ manifest JSONB DEFAULT '{}'::jsonb,
+ error_message TEXT,
+ extra JSONB DEFAULT '{}'::jsonb
+);
+COMMENT ON TABLE etl_admin.etl_run IS '运行记录表:记录每次任务执行的窗口、状态、计数与日志路径。';
+COMMENT ON COLUMN etl_admin.etl_run.run_uuid IS '本次调度的唯一标识。';
+COMMENT ON COLUMN etl_admin.etl_run.task_id IS '关联 etl_task.task_id。';
+COMMENT ON COLUMN etl_admin.etl_run.store_id IS '门店/租户粒度。';
+COMMENT ON COLUMN etl_admin.etl_run.status IS '运行状态(SUCC/FAIL/PARTIAL 等)。';
+COMMENT ON COLUMN etl_admin.etl_run.started_at IS '开始时间。';
+COMMENT ON COLUMN etl_admin.etl_run.ended_at IS '结束时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_start IS '本次窗口开始时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_end IS '本次窗口结束时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_minutes IS '窗口跨度(分钟)。';
+COMMENT ON COLUMN etl_admin.etl_run.overlap_seconds IS '窗口重叠秒数。';
+COMMENT ON COLUMN etl_admin.etl_run.fetched_count IS '抓取/读取的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.loaded_count IS '插入的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.updated_count IS '更新的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.skipped_count IS '跳过的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.error_count IS '错误记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.unknown_fields IS '未知字段计数(清洗阶段)。';
+COMMENT ON COLUMN etl_admin.etl_run.export_dir IS '抓取/导出目录。';
+COMMENT ON COLUMN etl_admin.etl_run.log_path IS '日志路径。';
+COMMENT ON COLUMN etl_admin.etl_run.request_params IS '请求参数 JSON。';
+COMMENT ON COLUMN etl_admin.etl_run.manifest IS '运行产出清单/统计 JSON。';
+COMMENT ON COLUMN etl_admin.etl_run.error_message IS '错误信息(若失败)。';
+COMMENT ON COLUMN etl_admin.etl_run.extra IS '附加字段,保留扩展。';
diff --git a/etl_billiards/database/schema_v2.sql b/etl_billiards/database/schema_v2.sql
deleted file mode 100644
index 392a9bd..0000000
--- a/etl_billiards/database/schema_v2.sql
+++ /dev/null
@@ -1,1128 +0,0 @@
--- Data warehouse schema for the entertainment chain (ODS -> DWD -> DWS)
--- ASCII only to keep cross-platform friendly.
-
-DROP SCHEMA IF EXISTS billiards_ods CASCADE;
-CREATE SCHEMA IF NOT EXISTS billiards_ods;
-CREATE SCHEMA IF NOT EXISTS billiards_dwd;
-CREATE SCHEMA IF NOT EXISTS billiards_dws;
-
--- ---------- ODS (raw, lightly typed) ----------
--- Each ODS table keeps the source payload for replay/debug while exposing key fields.
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_member_profile (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- member_id BIGINT NOT NULL,
- system_member_id BIGINT,
- register_site_id BIGINT,
- site_name TEXT,
- member_name TEXT,
- nickname TEXT,
- mobile TEXT,
- gender TEXT,
- birthday DATE,
- register_time TIMESTAMPTZ,
- member_type_id BIGINT,
- member_type_name TEXT,
- member_card_grade_code TEXT,
- status TEXT,
- user_status TEXT,
- balance NUMERIC(18,2),
- points NUMERIC(18,2),
- growth_value NUMERIC(18,2),
- last_visit_time TIMESTAMPTZ,
- wechat_id TEXT,
- alipay_id TEXT,
- member_card_no TEXT,
- referrer_member_id BIGINT,
- remarks TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, member_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_member_card (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- card_id BIGINT NOT NULL,
- member_id BIGINT,
- tenant_member_id BIGINT,
- card_type_id BIGINT,
- card_type_name TEXT,
- card_no TEXT,
- card_physics_type TEXT,
- card_balance NUMERIC(18,2),
- denomination NUMERIC(18,2),
- discount_rate NUMERIC(8,4),
- table_discount NUMERIC(18,2),
- goods_discount NUMERIC(18,2),
- assistant_discount NUMERIC(18,2),
- assistant_reward_discount NUMERIC(18,2),
- valid_start_date DATE,
- valid_end_date DATE,
- disable_start_date DATE,
- disable_end_date DATE,
- last_consume_time TIMESTAMPTZ,
- status TEXT,
- is_delete BOOLEAN,
- activate_time TIMESTAMPTZ,
- deactivate_time TIMESTAMPTZ,
- register_site_id BIGINT,
- issuer_id BIGINT,
- issuer_name TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, card_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_balance_change (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- change_id BIGINT NOT NULL,
- member_id BIGINT,
- tenant_member_id BIGINT,
- tenant_member_card_id BIGINT,
- member_name TEXT,
- member_mobile TEXT,
- change_amount NUMERIC(18,2),
- balance_before NUMERIC(18,2),
- balance_after NUMERIC(18,2),
- change_type INT,
- payment_method INT,
- refund_amount NUMERIC(18,2),
- relate_id BIGINT,
- register_site_id BIGINT,
- register_site_name TEXT,
- pay_site_name TEXT,
- remark TEXT,
- operator_id BIGINT,
- operator_name TEXT,
- change_time TIMESTAMPTZ,
- is_deleted BOOLEAN DEFAULT FALSE,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, change_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_recharge_record (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- recharge_id BIGINT NOT NULL,
- member_id BIGINT,
- recharge_amount NUMERIC(18,2),
- gift_amount NUMERIC(18,2),
- pay_method INT,
- pay_trade_no TEXT,
- order_trade_no TEXT,
- recharge_time TIMESTAMPTZ,
- status TEXT,
- operator_id BIGINT,
- operator_name TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, recharge_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_product (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- goods_id BIGINT NOT NULL,
- goods_name TEXT,
- goods_code TEXT,
- category_id BIGINT,
- category_name TEXT,
- goods_second_category_id BIGINT,
- unit TEXT,
- price NUMERIC(18,2),
- cost_price NUMERIC(18,2),
- market_price NUMERIC(18,2),
- goods_state TEXT,
- goods_cover TEXT,
- goods_bar_code TEXT,
- able_discount BOOLEAN,
- is_delete BOOLEAN,
- status TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, goods_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_store_product (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- site_goods_id BIGINT NOT NULL,
- goods_id BIGINT,
- goods_name TEXT,
- category_id BIGINT,
- category_name TEXT,
- unit TEXT,
- sale_price NUMERIC(18,2),
- cost_price NUMERIC(18,2),
- sale_num NUMERIC(18,2),
- stock_a NUMERIC(18,2),
- stock NUMERIC(18,2),
- provisional_total_cost NUMERIC(18,2),
- total_purchase_cost NUMERIC(18,2),
- batch_stock_quantity NUMERIC(18,2),
- goods_state TEXT,
- status TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, site_goods_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_store_sale_item (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- sale_item_id BIGINT NOT NULL,
- order_goods_id BIGINT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- site_goods_id BIGINT,
- goods_id BIGINT,
- goods_name TEXT,
- category_id BIGINT,
- quantity NUMERIC(18,4),
- unit_price NUMERIC(18,2),
- original_amount NUMERIC(18,2),
- discount_amount NUMERIC(18,2),
- final_amount NUMERIC(18,2),
- is_gift BOOLEAN DEFAULT FALSE,
- sale_time TIMESTAMPTZ,
- member_id BIGINT,
- salesman_id BIGINT,
- operator_id BIGINT,
- is_refunded BOOLEAN DEFAULT FALSE,
- discount_price NUMERIC(18,2),
- cost_money NUMERIC(18,2),
- coupon_deduct_amount NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- point_discount_money NUMERIC(18,2),
- point_discount_cost NUMERIC(18,2),
- sales_type TEXT,
- goods_remark TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, sale_item_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_info (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- table_id BIGINT NOT NULL,
- table_code TEXT,
- table_name TEXT,
- table_type TEXT,
- area_name TEXT,
- site_table_area_id BIGINT,
- tenant_table_area_id BIGINT,
- table_price NUMERIC(18,2),
- table_status TEXT,
- audit_status INT,
- show_status INT,
- light_status INT,
- virtual_table BOOLEAN,
- is_rest_area BOOLEAN,
- charge_free BOOLEAN,
- table_cloth_use_time INT,
- table_cloth_use_cycle INT,
- status TEXT,
- created_time TIMESTAMPTZ,
- updated_time TIMESTAMPTZ,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, table_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_use_log (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- ledger_id BIGINT NOT NULL,
- table_id BIGINT,
- table_name TEXT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- start_time TIMESTAMPTZ,
- end_time TIMESTAMPTZ,
- duration_seconds INT,
- billing_unit_price NUMERIC(18,4),
- billing_count NUMERIC(18,4),
- original_table_fee NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- coupon_discount_amount NUMERIC(18,2),
- manual_discount_amount NUMERIC(18,2),
- service_fee NUMERIC(18,2),
- final_table_fee NUMERIC(18,2),
- member_id BIGINT,
- operator_id BIGINT,
- salesman_id BIGINT,
- is_canceled BOOLEAN DEFAULT FALSE,
- cancel_time TIMESTAMPTZ,
- site_table_area_id BIGINT,
- tenant_table_area_id BIGINT,
- site_table_area_name TEXT,
- is_single_order BOOLEAN,
- used_card_amount NUMERIC(18,2),
- adjust_amount NUMERIC(18,2),
- coupon_promotion_amount NUMERIC(18,2),
- service_money NUMERIC(18,2),
- mgmt_fee NUMERIC(18,2),
- fee_total NUMERIC(18,2),
- real_table_use_seconds INT,
- last_use_time TIMESTAMPTZ,
- ledger_start_time TIMESTAMPTZ,
- ledger_end_time TIMESTAMPTZ,
- ledger_status INT,
- start_use_time TIMESTAMPTZ,
- add_clock_seconds INT,
- status TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, ledger_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_fee_adjust (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- adjust_id BIGINT NOT NULL,
- ledger_id BIGINT,
- order_trade_no TEXT,
- discount_amount NUMERIC(18,2),
- reason TEXT,
- operator_id BIGINT,
- operator_name TEXT,
- created_at TIMESTAMPTZ,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, adjust_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_account (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- assistant_id BIGINT NOT NULL,
- assistant_name TEXT,
- mobile TEXT,
- assistant_no INT,
- team_id BIGINT,
- team_name TEXT,
- group_id BIGINT,
- group_name TEXT,
- job_num TEXT,
- entry_type TEXT,
- leave_status TEXT,
- assistant_status TEXT,
- allow_cx BOOLEAN,
- status TEXT,
- hired_date DATE,
- left_date DATE,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, assistant_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_service_log (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- ledger_id BIGINT NOT NULL,
- assistant_id BIGINT,
- assistant_name TEXT,
- service_type TEXT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- start_time TIMESTAMPTZ,
- end_time TIMESTAMPTZ,
- duration_seconds INT,
- original_fee NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- manual_discount_amount NUMERIC(18,2),
- coupon_discount_amount NUMERIC(18,2),
- final_fee NUMERIC(18,2),
- member_id BIGINT,
- operator_id BIGINT,
- salesman_id BIGINT,
- is_canceled BOOLEAN DEFAULT FALSE,
- cancel_time TIMESTAMPTZ,
- skill_grade NUMERIC(10,2),
- service_grade NUMERIC(10,2),
- composite_grade NUMERIC(10,2),
- overall_score NUMERIC(10,2),
- status TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, ledger_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_cancel_log (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- cancel_id BIGINT NOT NULL,
- ledger_id BIGINT,
- assistant_id BIGINT,
- order_trade_no TEXT,
- table_id BIGINT,
- table_area_id BIGINT,
- table_area_name TEXT,
- table_name TEXT,
- assistant_on INT,
- pd_charge_minutes INT,
- assistant_abolish_amount NUMERIC(18,2),
- reason TEXT,
- cancel_time TIMESTAMPTZ,
- operator_id BIGINT,
- operator_name TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, cancel_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_group_package (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- package_id BIGINT NOT NULL,
- package_name TEXT,
- table_area_id BIGINT,
- table_area_name TEXT,
- platform_code TEXT,
- status TEXT,
- face_price NUMERIC(18,2),
- settle_price NUMERIC(18,2),
- selling_price NUMERIC(18,2),
- duration INT,
- valid_from DATE,
- valid_to DATE,
- start_time TIMESTAMPTZ,
- end_time TIMESTAMPTZ,
- is_enabled BOOLEAN,
- is_delete BOOLEAN,
- package_type TEXT,
- usable_count INT,
- creator_name TEXT,
- tenant_table_area_id BIGINT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, package_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_group_package_log (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- usage_id BIGINT NOT NULL,
- package_id BIGINT,
- coupon_id BIGINT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- status TEXT,
- used_time TIMESTAMPTZ,
- deduct_amount NUMERIC(18,2),
- settle_price NUMERIC(18,2),
- coupon_code TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, usage_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_platform_coupon_log (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- coupon_id BIGINT NOT NULL,
- platform_code TEXT,
- verify_code TEXT,
- coupon_code TEXT,
- coupon_channel TEXT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- status TEXT,
- used_time TIMESTAMPTZ,
- deduct_amount NUMERIC(18,2),
- settle_price NUMERIC(18,2),
- coupon_money NUMERIC(18,2),
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, coupon_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_inventory_change (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- change_id BIGINT NOT NULL,
- site_goods_id BIGINT,
- goods_id BIGINT,
- stock_type TEXT,
- change_amount NUMERIC(18,2),
- before_stock NUMERIC(18,2),
- after_stock NUMERIC(18,2),
- change_amount_alt NUMERIC(18,2),
- before_stock_alt NUMERIC(18,2),
- after_stock_alt NUMERIC(18,2),
- change_type TEXT,
- relate_id BIGINT,
- unit TEXT,
- price NUMERIC(18,2),
- goods_category_id BIGINT,
- goods_second_category_id BIGINT,
- remark TEXT,
- operator_id BIGINT,
- operator_name TEXT,
- change_time TIMESTAMPTZ,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, change_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_inventory_stock (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- site_goods_id BIGINT NOT NULL,
- goods_id BIGINT,
- goods_name TEXT,
- goods_unit TEXT,
- goods_category_id BIGINT,
- goods_second_category_id BIGINT,
- range_start_stock NUMERIC(18,2),
- range_end_stock NUMERIC(18,2),
- range_in NUMERIC(18,2),
- range_out NUMERIC(18,2),
- range_inventory NUMERIC(18,2),
- range_sale NUMERIC(18,2),
- range_sale_money NUMERIC(18,2),
- current_stock NUMERIC(18,2),
- cost_price NUMERIC(18,2),
- category_name TEXT,
- snapshot_key TEXT NOT NULL DEFAULT 'default',
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, site_goods_id, snapshot_key)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_order_settle (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- order_settle_id BIGINT NOT NULL,
- settle_relate_id BIGINT,
- settle_name TEXT,
- settle_type INT,
- settle_status INT,
- member_id BIGINT,
- member_name TEXT,
- member_phone TEXT,
- table_id BIGINT,
- consume_money NUMERIC(18,2),
- table_charge_money NUMERIC(18,2),
- goods_money NUMERIC(18,2),
- service_money NUMERIC(18,2),
- assistant_pd_money NUMERIC(18,2),
- assistant_cx_money NUMERIC(18,2),
- pay_amount NUMERIC(18,2),
- cash_amount NUMERIC(18,2),
- online_amount NUMERIC(18,2),
- point_amount NUMERIC(18,2),
- coupon_amount NUMERIC(18,2),
- card_amount NUMERIC(18,2),
- balance_amount NUMERIC(18,2),
- refund_amount NUMERIC(18,2),
- prepay_money NUMERIC(18,2),
- adjust_amount NUMERIC(18,2),
- rounding_amount NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- coupon_sale_amount NUMERIC(18,2),
- goods_promotion_money NUMERIC(18,2),
- assistant_promotion_money NUMERIC(18,2),
- point_discount_price NUMERIC(18,2),
- point_discount_cost NUMERIC(18,2),
- real_goods_money NUMERIC(18,2),
- assistant_manual_discount NUMERIC(18,2),
- all_coupon_discount NUMERIC(18,2),
- is_use_coupon BOOLEAN,
- is_use_discount BOOLEAN,
- is_activity BOOLEAN,
- is_bind_member BOOLEAN,
- is_first BOOLEAN,
- recharge_card_amount NUMERIC(18,2),
- gift_card_amount NUMERIC(18,2),
- payment_method INT,
- create_time TIMESTAMPTZ,
- pay_time TIMESTAMPTZ,
- revoke_order_id BIGINT,
- revoke_order_name TEXT,
- revoke_time TIMESTAMPTZ,
- can_be_revoked BOOLEAN,
- serial_number TEXT,
- sales_man_name TEXT,
- sales_man_user_id BIGINT,
- order_remark TEXT,
- operator_id BIGINT,
- operator_name TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, order_settle_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_goods_category (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- category_id BIGINT NOT NULL,
- category_name TEXT,
- parent_id BIGINT,
- level_no INT,
- status TEXT,
- remark TEXT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, category_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_payment_record (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- pay_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- pay_method_code TEXT,
- pay_method_name TEXT,
- pay_status INT,
- pay_amount NUMERIC(18,2),
- pay_time TIMESTAMPTZ,
- online_pay_channel TEXT,
- transaction_id TEXT,
- operator_id BIGINT,
- remark TEXT,
- relate_type TEXT,
- relate_id BIGINT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, pay_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_refund_record (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- refund_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- pay_sn TEXT,
- pay_amount NUMERIC(18,2),
- pay_status INT,
- is_revoke BOOLEAN,
- is_delete BOOLEAN,
- online_pay_channel TEXT,
- pay_method_code TEXT,
- refund_amount NUMERIC(18,2),
- refund_time TIMESTAMPTZ,
- action_type INT,
- pay_terminal INT,
- pay_config_id BIGINT,
- cashier_point_id BIGINT,
- operator_id BIGINT,
- member_card_id BIGINT,
- balance_frozen_amount NUMERIC(18,2),
- card_frozen_amount NUMERIC(18,2),
- round_amount NUMERIC(18,2),
- online_pay_type INT,
- channel_payer_id TEXT,
- channel_pay_no TEXT,
- check_status INT,
- channel_fee NUMERIC(18,2),
- relate_type TEXT,
- relate_id BIGINT,
- status TEXT,
- reason TEXT,
- related_payment_id BIGINT,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, refund_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_ods.ods_order_receipt_detail (
- tenant_id BIGINT,
- site_id BIGINT NOT NULL,
- order_settle_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_number TEXT,
- settle_type INT,
- receipt_no TEXT,
- receipt_time TIMESTAMPTZ,
- total_amount NUMERIC(18,2),
- discount_amount NUMERIC(18,2),
- final_amount NUMERIC(18,2),
- actual_payment NUMERIC(18,2),
- ledger_amount NUMERIC(18,2),
- member_offer_amount NUMERIC(18,2),
- delivery_fee NUMERIC(18,2),
- adjust_amount NUMERIC(18,2),
- payment_method INT,
- pay_time TIMESTAMPTZ,
- member_id BIGINT,
- order_remark TEXT,
- cashier_name TEXT,
- ticket_remark TEXT,
- ticket_custom_content TEXT,
- voucher_money NUMERIC(18,2),
- reward_name TEXT,
- consume_money NUMERIC(18,2),
- refund_amount NUMERIC(18,2),
- balance_amount NUMERIC(18,2),
- coupon_amount NUMERIC(18,2),
- member_deduct_amount NUMERIC(18,2),
- prepay_money NUMERIC(18,2),
- delivery_address TEXT,
- snapshot_raw JSONB,
- member_snapshot JSONB,
- source_file TEXT,
- source_endpoint TEXT,
- fetched_at TIMESTAMPTZ DEFAULT now(),
- payload JSONB NOT NULL,
- PRIMARY KEY (site_id, order_settle_id)
-);
-
--- ---------- DWD Dimensions ----------
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_tenant (
- tenant_id BIGINT PRIMARY KEY,
- tenant_name TEXT,
- short_name TEXT,
- status TEXT,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_site (
- site_id BIGINT PRIMARY KEY,
- tenant_id BIGINT,
- site_code TEXT,
- site_name TEXT,
- city TEXT,
- region TEXT,
- status TEXT,
- open_date DATE,
- close_date DATE,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_member_card_type (
- card_type_id BIGINT PRIMARY KEY,
- card_type_name TEXT,
- discount_rate NUMERIC(8,4),
- description TEXT,
- remark TEXT
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_product_category (
- category_id BIGINT PRIMARY KEY,
- category_name TEXT,
- parent_id BIGINT,
- level_no INT,
- status TEXT,
- remark TEXT
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_product (
- goods_id BIGINT PRIMARY KEY,
- goods_name TEXT,
- goods_code TEXT,
- category_id BIGINT REFERENCES billiards_dwd.dim_product_category (category_id),
- category_name TEXT,
- unit TEXT,
- default_price NUMERIC(18,2),
- status TEXT,
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_table (
- table_id BIGINT PRIMARY KEY,
- site_id BIGINT,
- table_code TEXT,
- table_name TEXT,
- table_type TEXT,
- area_name TEXT,
- status TEXT,
- created_time TIMESTAMPTZ,
- updated_time TIMESTAMPTZ
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_assistant_team (
- team_id BIGINT PRIMARY KEY,
- team_name TEXT,
- remark TEXT,
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_assistant (
- assistant_id BIGINT PRIMARY KEY,
- assistant_name TEXT,
- mobile TEXT,
- team_id BIGINT REFERENCES billiards_dwd.dim_assistant_team (team_id),
- status TEXT,
- hired_date DATE,
- left_date DATE,
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_pay_method (
- pay_method_code TEXT PRIMARY KEY,
- pay_method_name TEXT,
- is_stored_value BOOLEAN DEFAULT FALSE,
- status TEXT,
- updated_at TIMESTAMPTZ DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_order_assist_type (
- assist_type_code TEXT PRIMARY KEY,
- assist_type_name TEXT,
- description TEXT
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_coupon_platform (
- platform_code TEXT PRIMARY KEY,
- platform_name TEXT,
- description TEXT
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_date (
- date_key DATE PRIMARY KEY,
- year_no INT,
- month_no INT,
- day_no INT,
- week_no INT,
- day_of_week INT,
- month_name TEXT
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.dim_member (
- site_id BIGINT,
- member_id BIGINT,
- tenant_id BIGINT,
- member_name TEXT,
- nickname TEXT,
- gender TEXT,
- birthday DATE,
- mobile TEXT,
- member_type_id BIGINT REFERENCES billiards_dwd.dim_member_card_type (card_type_id),
- member_type_name TEXT,
- status TEXT,
- register_time TIMESTAMPTZ,
- valid_from DATE,
- valid_to DATE,
- last_visit_time TIMESTAMPTZ,
- balance NUMERIC(18,2),
- total_recharge_amount NUMERIC(18,2),
- total_consumed_amount NUMERIC(18,2),
- wechat_id TEXT,
- alipay_id TEXT,
- remark TEXT,
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, member_id)
-);
-
--- ---------- DWD Facts ----------
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_sale_item (
- site_id BIGINT NOT NULL,
- sale_item_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- goods_id BIGINT REFERENCES billiards_dwd.dim_product (goods_id),
- category_id BIGINT REFERENCES billiards_dwd.dim_product_category (category_id),
- quantity NUMERIC(18,4),
- original_amount NUMERIC(18,2),
- discount_amount NUMERIC(18,2),
- final_amount NUMERIC(18,2),
- is_gift BOOLEAN DEFAULT FALSE,
- sale_time TIMESTAMPTZ,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, sale_item_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_table_usage (
- site_id BIGINT NOT NULL,
- ledger_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- table_id BIGINT REFERENCES billiards_dwd.dim_table (table_id),
- member_id BIGINT,
- start_time TIMESTAMPTZ,
- end_time TIMESTAMPTZ,
- duration_minutes INT,
- original_table_fee NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- manual_discount_amount NUMERIC(18,2),
- final_table_fee NUMERIC(18,2),
- is_canceled BOOLEAN DEFAULT FALSE,
- cancel_time TIMESTAMPTZ,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, ledger_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_assistant_service (
- site_id BIGINT NOT NULL,
- ledger_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- assistant_id BIGINT REFERENCES billiards_dwd.dim_assistant (assistant_id),
- assist_type_code TEXT REFERENCES billiards_dwd.dim_order_assist_type (assist_type_code),
- member_id BIGINT,
- start_time TIMESTAMPTZ,
- end_time TIMESTAMPTZ,
- duration_minutes INT,
- original_fee NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- manual_discount_amount NUMERIC(18,2),
- final_fee NUMERIC(18,2),
- is_canceled BOOLEAN DEFAULT FALSE,
- cancel_time TIMESTAMPTZ,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, ledger_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_coupon_usage (
- site_id BIGINT NOT NULL,
- coupon_id BIGINT NOT NULL,
- package_id BIGINT,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- platform_code TEXT REFERENCES billiards_dwd.dim_coupon_platform (platform_code),
- status TEXT,
- deduct_amount NUMERIC(18,2),
- settle_price NUMERIC(18,2),
- used_time TIMESTAMPTZ,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, coupon_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_payment (
- site_id BIGINT NOT NULL,
- pay_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
- pay_amount NUMERIC(18,2),
- pay_time TIMESTAMPTZ,
- relate_type TEXT,
- relate_id BIGINT,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, pay_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_refund (
- site_id BIGINT NOT NULL,
- refund_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_settle_id BIGINT,
- member_id BIGINT,
- pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
- refund_amount NUMERIC(18,2),
- refund_time TIMESTAMPTZ,
- status TEXT,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, refund_id)
-);
-
-CREATE TABLE IF NOT EXISTS billiards_dwd.fact_balance_change (
- site_id BIGINT NOT NULL,
- change_id BIGINT NOT NULL,
- member_id BIGINT,
- change_type INT,
- relate_type TEXT,
- relate_id BIGINT,
- pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
- change_amount NUMERIC(18,2),
- balance_before NUMERIC(18,2),
- balance_after NUMERIC(18,2),
- change_time TIMESTAMPTZ,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, change_id)
-);
-
--- ---------- DWS (serving layers) ----------
-
-CREATE TABLE IF NOT EXISTS billiards_dws.dws_order_summary (
- site_id BIGINT NOT NULL,
- order_settle_id BIGINT NOT NULL,
- order_trade_no TEXT,
- order_date DATE,
- tenant_id BIGINT,
- member_id BIGINT,
- member_flag BOOLEAN DEFAULT FALSE,
- recharge_order_flag BOOLEAN DEFAULT FALSE,
- item_count INT,
- total_item_quantity NUMERIC(18,4),
- table_fee_amount NUMERIC(18,2),
- assistant_service_amount NUMERIC(18,2),
- goods_amount NUMERIC(18,2),
- group_amount NUMERIC(18,2),
- total_coupon_deduction NUMERIC(18,2),
- member_discount_amount NUMERIC(18,2),
- manual_discount_amount NUMERIC(18,2),
- order_original_amount NUMERIC(18,2),
- order_final_amount NUMERIC(18,2),
- stored_card_deduct NUMERIC(18,2),
- external_paid_amount NUMERIC(18,2),
- total_paid_amount NUMERIC(18,2),
- book_table_flow NUMERIC(18,2),
- book_assistant_flow NUMERIC(18,2),
- book_goods_flow NUMERIC(18,2),
- book_group_flow NUMERIC(18,2),
- book_order_flow NUMERIC(18,2),
- order_effective_consume_cash NUMERIC(18,2),
- order_effective_recharge_cash NUMERIC(18,2),
- order_effective_flow NUMERIC(18,2),
- refund_amount NUMERIC(18,2),
- net_income NUMERIC(18,2),
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- PRIMARY KEY (site_id, order_settle_id)
-);
-
--- ---------- etl_admin (scheduler, cursor, run tracking) ----------
-CREATE SCHEMA IF NOT EXISTS etl_admin;
-
-CREATE TABLE IF NOT EXISTS etl_admin.etl_task (
- task_id BIGSERIAL PRIMARY KEY,
- task_code TEXT NOT NULL,
- store_id BIGINT NOT NULL,
- enabled BOOLEAN DEFAULT TRUE,
- cursor_field TEXT,
- window_minutes_default INT DEFAULT 30,
- overlap_seconds INT DEFAULT 120,
- page_size INT DEFAULT 200,
- retry_max INT DEFAULT 3,
- params JSONB DEFAULT '{}'::jsonb,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- UNIQUE (task_code, store_id)
-);
-
-CREATE TABLE IF NOT EXISTS etl_admin.etl_cursor (
- cursor_id BIGSERIAL PRIMARY KEY,
- task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
- store_id BIGINT NOT NULL,
- last_start TIMESTAMPTZ,
- last_end TIMESTAMPTZ,
- last_id BIGINT,
- last_run_id BIGINT,
- extra JSONB DEFAULT '{}'::jsonb,
- created_at TIMESTAMPTZ DEFAULT now(),
- updated_at TIMESTAMPTZ DEFAULT now(),
- UNIQUE (task_id, store_id)
-);
-
-CREATE TABLE IF NOT EXISTS etl_admin.etl_run (
- run_id BIGSERIAL PRIMARY KEY,
- run_uuid TEXT NOT NULL,
- task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
- store_id BIGINT NOT NULL,
- status TEXT NOT NULL,
- started_at TIMESTAMPTZ DEFAULT now(),
- ended_at TIMESTAMPTZ,
- window_start TIMESTAMPTZ,
- window_end TIMESTAMPTZ,
- window_minutes INT,
- overlap_seconds INT,
- fetched_count INT DEFAULT 0,
- loaded_count INT DEFAULT 0,
- updated_count INT DEFAULT 0,
- skipped_count INT DEFAULT 0,
- error_count INT DEFAULT 0,
- unknown_fields INT DEFAULT 0,
- export_dir TEXT,
- log_path TEXT,
- request_params JSONB DEFAULT '{}'::jsonb,
- manifest JSONB DEFAULT '{}'::jsonb,
- error_message TEXT,
- extra JSONB DEFAULT '{}'::jsonb
-);
-
--- Default task registry seed (idempotent)
-INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
-VALUES
- ('PRODUCTS', 2790685415443269, TRUE),
- ('TABLES', 2790685415443269, TRUE),
- ('MEMBERS', 2790685415443269, TRUE),
- ('ASSISTANTS', 2790685415443269, TRUE),
- ('PACKAGES_DEF', 2790685415443269, TRUE),
- ('ORDERS', 2790685415443269, TRUE),
- ('PAYMENTS', 2790685415443269, TRUE),
- ('REFUNDS', 2790685415443269, TRUE),
- ('COUPON_USAGE', 2790685415443269, TRUE),
- ('INVENTORY_CHANGE', 2790685415443269, TRUE),
- ('TOPUPS', 2790685415443269, TRUE),
- ('TABLE_DISCOUNT', 2790685415443269, TRUE),
- ('ASSISTANT_ABOLISH', 2790685415443269, TRUE),
- ('LEDGER', 2790685415443269, TRUE),
- ('TICKET_DWD', 2790685415443269, TRUE),
- ('PAYMENTS_DWD', 2790685415443269, TRUE),
- ('MEMBERS_DWD', 2790685415443269, TRUE),
- ('MANUAL_INGEST', 2790685415443269, TRUE),
- ('ODS_ORDER_SETTLE', 2790685415443269, TRUE),
- ('ODS_TABLE_USE', 2790685415443269, TRUE),
- ('ODS_ASSISTANT_LEDGER', 2790685415443269, TRUE),
- ('ODS_ASSISTANT_ABOLISH', 2790685415443269, TRUE),
- ('ODS_GOODS_LEDGER', 2790685415443269, TRUE),
- ('ODS_PAYMENT', 2790685415443269, TRUE),
- ('ODS_REFUND', 2790685415443269, TRUE),
- ('ODS_COUPON_VERIFY', 2790685415443269, TRUE),
- ('ODS_MEMBER', 2790685415443269, TRUE),
- ('ODS_MEMBER_CARD', 2790685415443269, TRUE),
- ('ODS_PACKAGE', 2790685415443269, TRUE),
- ('ODS_INVENTORY_STOCK', 2790685415443269, TRUE),
- ('ODS_INVENTORY_CHANGE', 2790685415443269, TRUE)
-ON CONFLICT (task_code, store_id) DO NOTHING;
diff --git a/etl_billiards/database/seed_ods_tasks.sql b/etl_billiards/database/seed_ods_tasks.sql
index 04de63f..c0184d6 100644
--- a/etl_billiards/database/seed_ods_tasks.sql
+++ b/etl_billiards/database/seed_ods_tasks.sql
@@ -1,34 +1,37 @@
--- 将新的 ODS 任务注册到 etl_admin.etl_task(根据需要替换 store_id)
+-- 将新的 ODS 任务注册到 etl_admin.etl_task(按需替换 store_id)。
-- 使用方式(示例):
-- psql "$PG_DSN" -f etl_billiards/database/seed_ods_tasks.sql
--- 或者在 psql 中执行本文件内容。
+-- 或在 psql 中直接执行本文件内容。
WITH target_store AS (
SELECT 2790685415443269::bigint AS store_id -- TODO: 替换为实际 store_id
),
task_codes AS (
SELECT unnest(ARRAY[
- 'ODS_ASSISTANT_ACCOUNTS',
+ -- Must match tasks/ods_tasks.py (ENABLED_ODS_CODES)
+ 'ODS_ASSISTANT_ACCOUNT',
'ODS_ASSISTANT_LEDGER',
'ODS_ASSISTANT_ABOLISH',
- 'ODS_INVENTORY_CHANGE',
- 'ODS_INVENTORY_STOCK',
- 'ODS_PACKAGE',
- 'ODS_GROUP_BUY_REDEMPTION',
- 'ODS_MEMBER',
- 'ODS_MEMBER_BALANCE',
- 'ODS_MEMBER_CARD',
+ 'ODS_SETTLEMENT_RECORDS',
+ 'ODS_TABLE_USE',
'ODS_PAYMENT',
'ODS_REFUND',
- 'ODS_COUPON_VERIFY',
+ '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_TABLE_DISCOUNT',
+ 'ODS_STORE_GOODS_SALES',
+ 'ODS_TABLE_FEE_DISCOUNT',
'ODS_TENANT_GOODS',
- 'ODS_SETTLEMENT_TICKET',
- 'ODS_ORDER_SETTLE'
+ 'ODS_SETTLEMENT_TICKET'
]) AS task_code
)
INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
@@ -36,4 +39,3 @@ 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;
-
diff --git a/etl_billiards/database/seed_scheduler_tasks.sql b/etl_billiards/database/seed_scheduler_tasks.sql
new file mode 100644
index 0000000..2c62a61
--- /dev/null
+++ b/etl_billiards/database/seed_scheduler_tasks.sql
@@ -0,0 +1,50 @@
+-- Seed scheduler-compatible tasks into etl_admin.etl_task.
+--
+-- Notes:
+-- - These task_code values must match orchestration/task_registry.py.
+-- - ODS_* tasks are intentionally excluded here because they don't follow the
+-- BaseTask(cursor_data) scheduler interface in this repo version.
+--
+-- Usage (example):
+-- psql "%PG_DSN%" -f etl_billiards/database/seed_scheduler_tasks.sql
+--
+WITH target_store AS (
+ SELECT 2790685415443269::bigint AS store_id -- TODO: replace with your store_id
+),
+task_codes AS (
+ SELECT unnest(ARRAY[
+ 'ASSISTANT_ABOLISH',
+ 'ASSISTANTS',
+ 'COUPON_USAGE',
+ 'CHECK_CUTOFF',
+ 'DATA_INTEGRITY_CHECK',
+ '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'
+ ]) AS task_code
+)
+INSERT INTO etl_admin.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();
diff --git a/etl_billiards/dist/ETL_Manager/ETL_Manager.exe b/etl_billiards/dist/ETL_Manager/ETL_Manager.exe
new file mode 100644
index 0000000..4c8e672
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/ETL_Manager.exe differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/LIBBZ2.dll b/etl_billiards/dist/ETL_Manager/_internal/LIBBZ2.dll
new file mode 100644
index 0000000..74d8857
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/LIBBZ2.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/MSVCP140.dll b/etl_billiards/dist/ETL_Manager/_internal/MSVCP140.dll
new file mode 100644
index 0000000..5a1cb64
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/MSVCP140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140.dll
new file mode 100644
index 0000000..cefb988
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_1.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_1.dll
new file mode 100644
index 0000000..9346cb5
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_1.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_2.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_2.dll
new file mode 100644
index 0000000..038f5af
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/MSVCP140_2.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Core.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Core.dll
new file mode 100644
index 0000000..3bb514e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Core.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Gui.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Gui.dll
new file mode 100644
index 0000000..cf497ab
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Gui.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Network.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Network.dll
new file mode 100644
index 0000000..629346d
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Network.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6OpenGL.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6OpenGL.dll
new file mode 100644
index 0000000..fa371dd
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6OpenGL.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Pdf.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Pdf.dll
new file mode 100644
index 0000000..8cf71ef
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Pdf.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Qml.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Qml.dll
new file mode 100644
index 0000000..bfc290c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Qml.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlMeta.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlMeta.dll
new file mode 100644
index 0000000..a821374
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlMeta.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlModels.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlModels.dll
new file mode 100644
index 0000000..0fd70ad
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlModels.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlWorkerScript.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlWorkerScript.dll
new file mode 100644
index 0000000..3643679
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6QmlWorkerScript.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Quick.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Quick.dll
new file mode 100644
index 0000000..ae1a24e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Quick.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Svg.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Svg.dll
new file mode 100644
index 0000000..453ad91
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Svg.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6VirtualKeyboard.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6VirtualKeyboard.dll
new file mode 100644
index 0000000..5feca02
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6VirtualKeyboard.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Widgets.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Widgets.dll
new file mode 100644
index 0000000..046f4d0
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/Qt6Widgets.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140.dll
new file mode 100644
index 0000000..cee70b5
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140_1.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140_1.dll
new file mode 100644
index 0000000..a46c5ba
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/VCRUNTIME140_1.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/opengl32sw.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/opengl32sw.dll
new file mode 100644
index 0000000..7ab91c2
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/opengl32sw.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/generic/qtuiotouchplugin.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/generic/qtuiotouchplugin.dll
new file mode 100644
index 0000000..dcfacd8
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/generic/qtuiotouchplugin.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/iconengines/qsvgicon.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/iconengines/qsvgicon.dll
new file mode 100644
index 0000000..61b6ecb
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/iconengines/qsvgicon.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qgif.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qgif.dll
new file mode 100644
index 0000000..1185f94
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qgif.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qicns.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qicns.dll
new file mode 100644
index 0000000..6e75f1c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qicns.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qico.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qico.dll
new file mode 100644
index 0000000..af589da
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qico.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qjpeg.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qjpeg.dll
new file mode 100644
index 0000000..6986cae
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qjpeg.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qpdf.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qpdf.dll
new file mode 100644
index 0000000..ff752a3
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qpdf.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qsvg.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qsvg.dll
new file mode 100644
index 0000000..cb9b8cd
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qsvg.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtga.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtga.dll
new file mode 100644
index 0000000..0b5911a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtga.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtiff.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtiff.dll
new file mode 100644
index 0000000..f5ed6dc
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qtiff.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwbmp.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwbmp.dll
new file mode 100644
index 0000000..7e284a8
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwbmp.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwebp.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwebp.dll
new file mode 100644
index 0000000..1bf4197
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/imageformats/qwebp.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/networkinformation/qnetworklistmanager.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/networkinformation/qnetworklistmanager.dll
new file mode 100644
index 0000000..a1c740e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/networkinformation/qnetworklistmanager.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforminputcontexts/qtvirtualkeyboardplugin.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforminputcontexts/qtvirtualkeyboardplugin.dll
new file mode 100644
index 0000000..3476b34
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforminputcontexts/qtvirtualkeyboardplugin.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qdirect2d.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qdirect2d.dll
new file mode 100644
index 0000000..4ba4f87
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qdirect2d.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qminimal.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qminimal.dll
new file mode 100644
index 0000000..1cce328
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qminimal.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qoffscreen.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qoffscreen.dll
new file mode 100644
index 0000000..96d07fa
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qoffscreen.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qwindows.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qwindows.dll
new file mode 100644
index 0000000..64e6c14
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/platforms/qwindows.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/styles/qmodernwindowsstyle.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/styles/qmodernwindowsstyle.dll
new file mode 100644
index 0000000..a06741c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/styles/qmodernwindowsstyle.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qcertonlybackend.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qcertonlybackend.dll
new file mode 100644
index 0000000..123843a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qcertonlybackend.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qopensslbackend.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qopensslbackend.dll
new file mode 100644
index 0000000..63b120e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qopensslbackend.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qschannelbackend.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qschannelbackend.dll
new file mode 100644
index 0000000..ac0ad9f
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/plugins/tls/qschannelbackend.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/pyside6.abi3.dll b/etl_billiards/dist/ETL_Manager/_internal/PySide6/pyside6.abi3.dll
new file mode 100644
index 0000000..fd9bc40
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/pyside6.abi3.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ar.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ar.qm
new file mode 100644
index 0000000..ddce1e8
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ar.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_bg.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_bg.qm
new file mode 100644
index 0000000..3b5c3ad
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_bg.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ca.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ca.qm
new file mode 100644
index 0000000..6b46339
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ca.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_cs.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_cs.qm
new file mode 100644
index 0000000..95be1ea
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_cs.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_da.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_da.qm
new file mode 100644
index 0000000..3ffc148
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_da.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_de.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_de.qm
new file mode 100644
index 0000000..dec7e14
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_de.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_en.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_en.qm
new file mode 100644
index 0000000..937ea3e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_en.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_es.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_es.qm
new file mode 100644
index 0000000..7ea8766
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_es.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fa.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fa.qm
new file mode 100644
index 0000000..b964c32
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fa.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fi.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fi.qm
new file mode 100644
index 0000000..a4cb291
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fi.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fr.qm
new file mode 100644
index 0000000..7d74c4a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_fr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gd.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gd.qm
new file mode 100644
index 0000000..7b4d040
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gd.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gl.qm
new file mode 100644
index 0000000..5255734
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_gl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_he.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_he.qm
new file mode 100644
index 0000000..c9d3107
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_he.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ar.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ar.qm
new file mode 100644
index 0000000..aa92f02
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ar.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_bg.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_bg.qm
new file mode 100644
index 0000000..c65d260
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_bg.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ca.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ca.qm
new file mode 100644
index 0000000..43fd055
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ca.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_cs.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_cs.qm
new file mode 100644
index 0000000..fd50d84
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_cs.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_da.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_da.qm
new file mode 100644
index 0000000..2c26d75
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_da.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_de.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_de.qm
new file mode 100644
index 0000000..a6b85a0
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_de.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_en.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_en.qm
new file mode 100644
index 0000000..937ea3e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_en.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_es.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_es.qm
new file mode 100644
index 0000000..94e3967
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_es.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_fr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_fr.qm
new file mode 100644
index 0000000..4703e91
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_fr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_gl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_gl.qm
new file mode 100644
index 0000000..aef1ab6
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_gl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hr.qm
new file mode 100644
index 0000000..2151a78
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hu.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hu.qm
new file mode 100644
index 0000000..6c4db44
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_hu.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_it.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_it.qm
new file mode 100644
index 0000000..e3bc252
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_it.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ja.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ja.qm
new file mode 100644
index 0000000..e64507a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ja.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ka.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ka.qm
new file mode 100644
index 0000000..ec0ad83
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ka.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ko.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ko.qm
new file mode 100644
index 0000000..f6b1d13
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ko.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nl.qm
new file mode 100644
index 0000000..eb22989
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nn.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nn.qm
new file mode 100644
index 0000000..aa47765
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_nn.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pl.qm
new file mode 100644
index 0000000..c2b82b2
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pt_BR.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pt_BR.qm
new file mode 100644
index 0000000..21b5d02
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_pt_BR.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ru.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ru.qm
new file mode 100644
index 0000000..2a7d88b
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_ru.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sk.qm
new file mode 100644
index 0000000..8a4a447
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sl.qm
new file mode 100644
index 0000000..fd122a6
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sv.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sv.qm
new file mode 100644
index 0000000..834bdf7
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_sv.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_tr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_tr.qm
new file mode 100644
index 0000000..52178a8
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_tr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_uk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_uk.qm
new file mode 100644
index 0000000..192d28d
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_uk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_CN.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_CN.qm
new file mode 100644
index 0000000..2eb396f
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_CN.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_TW.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_TW.qm
new file mode 100644
index 0000000..0f41b44
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_help_zh_TW.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hr.qm
new file mode 100644
index 0000000..0a1f8cd
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hu.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hu.qm
new file mode 100644
index 0000000..c6908fc
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_hu.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_it.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_it.qm
new file mode 100644
index 0000000..9cfb64c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_it.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ja.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ja.qm
new file mode 100644
index 0000000..cd4aea4
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ja.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ka.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ka.qm
new file mode 100644
index 0000000..ec430b0
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ka.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ko.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ko.qm
new file mode 100644
index 0000000..b8528c9
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ko.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lg.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lg.qm
new file mode 100644
index 0000000..3e7e410
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lg.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lt.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lt.qm
new file mode 100644
index 0000000..e9c36fe
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lt.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lv.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lv.qm
new file mode 100644
index 0000000..6c1126a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_lv.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nl.qm
new file mode 100644
index 0000000..936ca0d
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nn.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nn.qm
new file mode 100644
index 0000000..58c5ca1
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_nn.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pl.qm
new file mode 100644
index 0000000..19d6c0f
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_BR.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_BR.qm
new file mode 100644
index 0000000..fe8dc29
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_BR.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_PT.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_PT.qm
new file mode 100644
index 0000000..03353ea
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_pt_PT.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ru.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ru.qm
new file mode 100644
index 0000000..3268b91
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_ru.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sk.qm
new file mode 100644
index 0000000..a9b0035
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sl.qm
new file mode 100644
index 0000000..bc2073b
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sv.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sv.qm
new file mode 100644
index 0000000..f8c9010
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_sv.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_tr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_tr.qm
new file mode 100644
index 0000000..4163108
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_tr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_uk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_uk.qm
new file mode 100644
index 0000000..42abff3
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_uk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_CN.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_CN.qm
new file mode 100644
index 0000000..f35616c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_CN.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_TW.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_TW.qm
new file mode 100644
index 0000000..ea03c3d
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qt_zh_TW.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ar.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ar.qm
new file mode 100644
index 0000000..32861b8
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ar.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_bg.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_bg.qm
new file mode 100644
index 0000000..faeb167
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_bg.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ca.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ca.qm
new file mode 100644
index 0000000..4e362dc
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ca.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_cs.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_cs.qm
new file mode 100644
index 0000000..459ef26
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_cs.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_da.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_da.qm
new file mode 100644
index 0000000..4ede24b
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_da.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_de.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_de.qm
new file mode 100644
index 0000000..50202fe
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_de.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_en.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_en.qm
new file mode 100644
index 0000000..937ea3e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_en.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_es.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_es.qm
new file mode 100644
index 0000000..1a13157
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_es.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fa.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fa.qm
new file mode 100644
index 0000000..aadc0c1
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fa.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fi.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fi.qm
new file mode 100644
index 0000000..934aecd
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fi.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fr.qm
new file mode 100644
index 0000000..19f0ba5
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_fr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_gd.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_gd.qm
new file mode 100644
index 0000000..3fe3841
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_gd.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_he.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_he.qm
new file mode 100644
index 0000000..95ed0c7
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_he.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hr.qm
new file mode 100644
index 0000000..4ed06fb
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hu.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hu.qm
new file mode 100644
index 0000000..291bb89
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_hu.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_it.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_it.qm
new file mode 100644
index 0000000..a4175b5
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_it.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ja.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ja.qm
new file mode 100644
index 0000000..acd2f03
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ja.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ka.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ka.qm
new file mode 100644
index 0000000..2756e92
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ka.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ko.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ko.qm
new file mode 100644
index 0000000..20e4661
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ko.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lg.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lg.qm
new file mode 100644
index 0000000..1cc6285
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lg.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lv.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lv.qm
new file mode 100644
index 0000000..f88a761
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_lv.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nl.qm
new file mode 100644
index 0000000..de4e74a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nn.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nn.qm
new file mode 100644
index 0000000..506ec45
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_nn.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pl.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pl.qm
new file mode 100644
index 0000000..3c4e03b
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pl.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pt_BR.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pt_BR.qm
new file mode 100644
index 0000000..6fabd0e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_pt_BR.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ru.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ru.qm
new file mode 100644
index 0000000..c1a2286
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_ru.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sk.qm
new file mode 100644
index 0000000..55a377e
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sv.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sv.qm
new file mode 100644
index 0000000..f86d8d0
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_sv.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_tr.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_tr.qm
new file mode 100644
index 0000000..efed395
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_tr.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_uk.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_uk.qm
new file mode 100644
index 0000000..21a3038
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_uk.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_CN.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_CN.qm
new file mode 100644
index 0000000..6591a69
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_CN.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_TW.qm b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_TW.qm
new file mode 100644
index 0000000..f32a72f
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/PySide6/translations/qtbase_zh_TW.qm differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140.dll b/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140.dll
new file mode 100644
index 0000000..2e2bb47
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140_1.dll b/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140_1.dll
new file mode 100644
index 0000000..dd0c100
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/VCRUNTIME140_1.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/base_library.zip b/etl_billiards/dist/ETL_Manager/_internal/base_library.zip
new file mode 100644
index 0000000..7353740
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/base_library.zip differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/comerr64.dll b/etl_billiards/dist/ETL_Manager/_internal/comerr64.dll
new file mode 100644
index 0000000..fb5f3e9
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/comerr64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/schema_ODS_doc.sql b/etl_billiards/dist/ETL_Manager/_internal/database/schema_ODS_doc.sql
new file mode 100644
index 0000000..d194c25
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/schema_ODS_doc.sql
@@ -0,0 +1,1945 @@
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS 'ODS 原始明细表:会员档案/会员账户信息。来源:export/test-json-doc/member_profiles.json;分析:member_profiles-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '【说明】会员的注册门店 ID。 【示例】2790685415443269(用于会员的注册门店 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '【说明】注册门店名称,属于冗余字段,用于直接展示。 【示例】朗朗桌球(注册门店名称,属于冗余字段,用于直接展示)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - site_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '【说明】这是“租户内会员账户”的主键 ID。 【示例】2955204541320325(用于这是“租户内会员账户”的主键 ID)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '【说明】这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。 【示例】2955204540009605(用于这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '【说明】这两个字段是成对出现的:一个数值码,一个中文名称。 【示例】2790683528022853(用于这两个字段是成对出现的:一个数值码,一个中文名称)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '【说明】这是“会员卡种类/等级”的定义字段。 【示例】储值卡(用于这是“会员卡种类/等级”的定义字段)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '【说明】会员绑定的手机号码。 【示例】18620043391(用于会员绑定的手机号码)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - mobile。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '【说明】会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。 【示例】胡先生(用于会员在当前租户下的显示名称(可以是姓名,也可以是昵称))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - nickname。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '【说明】当前积分余额(这条会员账户的积分值)。 【示例】0.0(用于当前积分余额(这条会员账户的积分值))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - point。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '【说明】成长值 / 经验值,用于会员等级晋升的累计指标。 【示例】0.0(成长值 / 经验值,用于会员等级晋升的累计指标)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - growth_value。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '【说明】推荐人会员 ID,用于记录该会员是由哪位老会员推荐。 【示例】0(推荐人会员 ID,用于记录该会员是由哪位老会员推荐)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - referrer_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '【说明】帐户状态(偏“卡状态/档案状态”)。 【示例】1(用于帐户状态(偏“卡状态/档案状态”))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '【说明】用户账号状态(偏“用户逻辑”层面的状态)。 【示例】1(用于用户账号状态(偏“用户逻辑”层面的状态))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - user_status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '【说明】会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。 【示例】2025-11-08 01:29:33(用于会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间))。 【JSON字段】member_profiles.json - data.tenantMemberInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_profiles.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_profiles.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_profiles.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_profiles.json - data.tenantMemberInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS 'ODS 原始明细表:会员余额变更流水。来源:export/test-json-doc/member_balance_changes.json;分析:member_balance_changes-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '【说明】租户/商户 ID,本数据中是固定值(同一品牌/商户)。 【示例】2790683160709957(用于租户/商户 ID,本数据中是固定值(同一品牌/商户))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '【说明】非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致)。 【示例】2790685415443269(用于非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '【说明】会员卡的“注册门店 ID”,即办卡所在门店。 【示例】2790685415443269(用于会员卡的“注册门店 ID”,即办卡所在门店)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '【说明】卡片的注册门店名称(办卡地点),和 register_site_id 配套。 【示例】朗朗桌球(用于卡片的注册门店名称(办卡地点),和 register_site_id 配套)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - registerSiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '【说明】发生本次余额变更的门店名称(即本次消费/充值所在门店)。 【示例】朗朗桌球(用于发生本次余额变更的门店名称(即本次消费/充值所在门店))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - paySiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '【说明】余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。 【示例】2957881605869253(用于余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '【说明】商户维度的会员 ID(租户内会员主键)。 【示例】2799212845565701(用于商户维度的会员 ID(租户内会员主键))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '【说明】会员卡账户 ID,在租户内唯一标识某张卡。 【示例】2799219999295237(用于会员卡账户 ID,在租户内唯一标识某张卡)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_card_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '【说明】系统级(全局)会员 ID。 【示例】2799212844549893(用于系统级(全局)会员 ID)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '【说明】会员姓名或称呼(非昵称字段)。 【示例】曾丹烨(用于会员姓名或称呼(非昵称字段))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '【说明】会员手机号。 【示例】13922213242(用于会员手机号)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberMobile。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '【说明】卡种类型 ID,用于区分不同卡种。 【示例】2793249295533893(卡种类型 ID,用于区分不同卡种)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '【说明】卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。 【示例】储值卡(用于卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberCardTypeName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '【说明】本次变动的金额(元),正数表示增加,负数表示减少。 【示例】-120.0(用于本次变动的金额(元),正数表示增加,负数表示减少)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - account_data。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '【说明】本次变动前,该卡账户的余额(元)。 【示例】816.3(用于本次变动前,该卡账户的余额(元))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - before。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '【说明】本次变动后,该卡账户的余额(元)。 【示例】696.3(用于本次变动后,该卡账户的余额(元))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - after。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '【说明】可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。 【示例】0.0(可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - refund_amount。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - from_type。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - payment_method。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '【说明】例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。 【示例】2957881518788421(用于例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - relate_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '【说明】当为空时,说明这条变动没有额外备注说明。 【示例】充值退款(用于当为空时,说明这条变动没有额外备注说明)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - remark。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '【说明】执行此次余额变更操作的员工 ID。 【示例】2790687322443013(用于执行此次余额变更操作的员工 ID)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '【说明】操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。 【示例】收银员:郑丽珊(用于操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_name。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - is_delete。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '【说明】本条余额变更记录的创建时间,通常接近交易发生时间。 【示例】2025-11-09 22:52:48(用于本条余额变更记录的创建时间,通常接近交易发生时间)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - create_time。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_balance_changes.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_balance_changes.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_balance_changes.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS 'ODS 原始明细表:会员储值/卡券账户列表。来源:export/test-json-doc/member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '【说明】租户/品牌 ID,与其他 JSON 中 tenant_id 一致。 【示例】2790683160709957(用于租户/品牌 ID,与其他 JSON 中 tenant_id 一致)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '【说明】当前商户(品牌/租户)中会员的主键 ID。 【示例】2955204541320325(用于当前商户(品牌/租户)中会员的主键 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '【说明】系统级会员 ID(跨门店统一主键)。 【示例】2955204540009605(用于系统级会员 ID(跨门店统一主键))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '【说明】卡首次办理的门店 ID。 【示例】2790685415443269(用于卡首次办理的门店 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '【说明】卡归属门店名称(视图中的展示字段)。 【示例】朗朗桌球(用于卡归属门店名称(视图中的展示字段))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - site_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2955206162843781(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '【说明】卡等级/卡类代码,和下面两个名称字段一一对应。 【示例】2790683528022856(用于卡等级/卡类代码,和下面两个名称字段一一对应)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '【说明】卡等级/卡类名称。 【示例】活动抵用券(用于卡等级/卡类名称)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '【说明】卡类型名称,实际与 member_card_grade_code_name 一致。 【示例】活动抵用券(用于卡类型名称,实际与 member_card_grade_code_name 一致)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_type_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '【说明】持卡会员姓名快照。 【示例】胡先生(用于持卡会员姓名快照)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '【说明】持卡会员手机号快照。 【示例】18620043391(用于持卡会员手机号快照)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_mobile。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '【说明】卡种 ID(定义“这是哪一种卡”)。 【示例】2793266846533445(用于卡种 ID(定义“这是哪一种卡”))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '【说明】实体卡物理卡号/条码号。 【示例】NULL(用于实体卡物理卡号/条码号)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_no。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '【说明】物理卡类型。 【示例】1(用于物理卡类型)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_physics_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '【说明】当前卡内余额(主要针对储值卡、部分券卡)。 【示例】0.0(用于当前卡内余额(主要针对储值卡、部分券卡))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - balance。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '【说明】采用“几折”的记法:10=不打折,9=九折,8=八折。 【示例】0.0(用于采用“几折”的记法:10=不打折,9=九折,8=八折)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - denomination。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCarDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '【说明】助教奖励金方向扣款的配置。 【示例】0.0(用于助教奖励金方向扣款的配置)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantRewardCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '【说明】结算时从卡中扣除的金额上限/规则配置(视图级。 【示例】0.0(用于结算时从卡中扣除的金额上限/规则配置(视图级)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cardSettleDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '【说明】与卡绑定的“券额度扣除配置”。 【示例】0.0(用于与卡绑定的“券额度扣除配置”)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - couponCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '【说明】配送费可否/多少从卡中抵扣,目前无业务发生。 【示例】0.0(用于配送费可否/多少从卡中抵扣,目前无业务发生)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - deliveryFeeDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '【说明】卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。 【示例】NULL(用于卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - use_scene。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '【说明】是否允许跨店使用。 【示例】1(用于是否允许跨店使用)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_cross_site。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】NULL(布尔/开关字段,用于表示权限、可用性或状态开关)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '【说明】是否允许转赠/转让给其他会员。 【示例】0(用于是否允许转赠/转让给其他会员)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_give。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '【说明】是否允许在“订单层面统一扣款”。 【示例】0(用于是否允许在“订单层面统一扣款”)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_order_deduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_delete。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '【说明】卡绑定密码,用于消费或查询验证(目前未启用)。 【示例】NULL(卡绑定密码,用于消费或查询验证(目前未启用))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - bind_password。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_range_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '【说明】可用的商品分类 ID 列表。 【示例】[](用于可用的商品分类 ID 列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '【说明】限定可使用的台区 ID 列表。 【示例】[](用于限定可使用的台区 ID 列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableAreaId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '【说明】卡片限定生效门店 ID。 【示例】0(用于卡片限定生效门店 ID)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - effect_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '【说明】卡片生效开始时间(有效期起始)。 【示例】2025-11-08 01:31:12(用于卡片生效开始时间(有效期起始))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '【说明】卡片有效期结束时间。 【示例】2225-01-01 00:00:00(用于卡片有效期结束时间)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '【说明】最近一次消费时间。 【示例】2025-11-09 07:48:23(用于最近一次消费时间)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - last_consume_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '【说明】卡片创建时间(开卡时间)。 【示例】2025-11-08 01:31:12(用于卡片创建时间(开卡时间))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - create_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '【说明】状态枚举,用于标识记录当前业务状态。 【示例】1(状态枚举,用于标识记录当前业务状态。)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - status。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '【说明】在前端展示或某些列表中的排序权重。 【示例】1(用于在前端展示或某些列表中的排序权重)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - sort。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '【说明】品牌头像 URL(未配置)。 【示例】NULL(用于品牌头像 URL(未配置))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantAvatar。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '【说明】租户/品牌名称(当前导出为空)。 【示例】NULL(用于租户/品牌名称(当前导出为空))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantName。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '【说明】允许使用的“陪打/助教等级”列表。 【示例】[](用于允许使用的“陪打/助教等级”列表)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - pdAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '【说明】可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写)。 【示例】[](用于可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写))。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cxAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_stored_value_cards.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_stored_value_cards.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】member_stored_value_cards.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS 'ODS 原始明细表:充值结算记录。来源:export/test-json-doc/recharge_settlements.json;分析:recharge_settlements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - siteid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - sitename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - createtime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - memberid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - membername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - tableid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - payamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - settlename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - settletype。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】recharge_settlements.json - $ - paytime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】recharge_settlements.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - canberevoked。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isusecoupon。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】recharge_settlements.json - $ - isusediscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isactivity。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】recharge_settlements.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】recharge_settlements.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】recharge_settlements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/recharge_settlements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】recharge_settlements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】recharge_settlements.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS 'ODS 原始明细表:结账/结算记录。来源:export/test-json-doc/settlement_records.json;分析:settlement_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '【说明】结账记录主键 ID(订单结算 ID)。 【示例】NULL(用于结账记录主键 ID(订单结算 ID))。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - siteid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - sitename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - createtime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - memberid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - membername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - tableid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - payamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - settlename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - settletype。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】settlement_records.json - $ - paytime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlement_records.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - canberevoked。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isusecoupon。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】settlement_records.json - $ - isusediscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isactivity。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_records.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】settlement_records.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】settlement_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】settlement_records.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS 'ODS 原始明细表:助教作废/取消记录。来源:export/test-json-doc/assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2957675849518789(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '【说明】门店 ID,即该废除记录所在门店。 【示例】2790685415443269(用于门店 ID,即该废除记录所在门店)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '【说明】助教姓名/对外展示名称。 【示例】泡芙(用于助教姓名/对外展示名称)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '【说明】与“助教废除”关联的金额字段。 【示例】5.83(用于与“助教废除”关联的金额字段)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantAbolishAmount。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '【说明】助教编号(工号/序号)。 【示例】27(用于助教编号(工号/序号))。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantOn。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '【说明】“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟。 【示例】214(用于“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - pdChargeMinutes。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '【说明】台桌所在区域 ID。 【示例】2791963816579205(用于台桌所在区域 ID)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableAreaId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '【说明】台桌所属区域名称。 【示例】C区(用于台桌所属区域名称)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableArea。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '【说明】球台/桌子的 ID。 【示例】2793016660660357(用于球台/桌子的 ID)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '【说明】台桌名称/编号,供人阅读。 【示例】C1(用于台桌名称/编号,供人阅读)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '【说明】用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等。 【示例】NULL(用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - trashReason。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '【说明】这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻。 【示例】2025-11-09 19:23:29(用于这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - createTime。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_cancellation_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_cancellation_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_cancellation_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ birth_date TIMESTAMP,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ last_update_name TEXT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS 'ODS 原始明细表:助教档案主数据。来源:export/test-json-doc/assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '【说明】助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。 【示例】2947562271297029(用于助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '【说明】品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。 【示例】2790683160709957(用于品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '【说明】门店 ID,对应本次数据的这家球房(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,对应本次数据的这家球房(朗朗桌球))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '【说明】助教工号 / 编号,便于业务侧识别。 【示例】31(用于助教工号 / 编号,便于业务侧识别)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '【说明】助教在前台展示的昵称,如“佳怡”“周周”“球球”等。 【示例】小然(用于助教在前台展示的昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '【说明】助教真实姓名,如“何海婷”“梁婷婷”等。 【示例】张静然(用于助教真实姓名,如“何海婷”“梁婷婷”等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - real_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '【说明】助教手机号,用于登录绑定、通知、钉钉同步等。 【示例】15119679931(助教手机号,用于登录绑定、通知、钉钉同步等)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - mobile。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '【说明】团队名称,展示用,和 team_id 一一对应。 【示例】1组(用于团队名称,展示用,和 team_id 一一对应)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '【说明】系统级“用户账号 ID”,通常对应登录账号。 【示例】2947562270838277(用于系统级“用户账号 ID”,通常对应登录账号)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '【说明】10 × 24。 【示例】20(用于10 × 24)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - level。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '【说明】1 × 48。 【示例】1(用于1 × 48)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '【说明】当 leave_status = 0 时,work_status = 1。 【示例】2(用于当 leave_status = 0 时,work_status = 1)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - work_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '【说明】0 × 21。 【示例】1(用于0 × 21)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - leave_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '【说明】入职时间。 【示例】2025-11-02 08:00:00(用于入职时间)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '【说明】离职日期。 【示例】2025-11-03 08:00:00(用于离职日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '【说明】当前配置生效的开始日期。 【示例】2025-11-01 08:00:00(用于当前配置生效的开始日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '【说明】当前配置生效的结束日期(例如一个周期性的排班/合同周期)。 【示例】2025-12-01 08:00:00(用于当前配置生效的结束日期(例如一个周期性的排班/合同周期))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '【说明】账号创建时间。 【示例】2025-11-02 15:55:26(用于账号创建时间)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '【说明】账号最近一次被修改的时间(例如修改等级、昵称等)。 【示例】2025-11-03 18:32:07(用于账号最近一次被修改的时间(例如修改等级、昵称等))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - update_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '【说明】该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。 【示例】0(该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '【说明】预留给“人事系统员工 ID”的字段,目前未接入或未启用。 【示例】0(用于预留给“人事系统员工 ID”的字段,目前未接入或未启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '【说明】人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。 【示例】0(用于人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_profile_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】10(标识类 ID 字段,用于关联/定位相关实体)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - system_role_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '【说明】助教头像地址。 【示例】https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(用于助教头像地址)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - avatar。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.birth_date IS '【说明】助教出生日期。 【示例】0001-01-01 00:00:00(用于助教出生日期)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - birth_date。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '【说明】0 × 40。 【示例】0(用于0 × 40)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - gender。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '【说明】身高(单位:厘米)。 【示例】0.0(用于身高(单位:厘米))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - height。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '【说明】体重(单位:公斤)。 【示例】0.0(用于体重(单位:公斤))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - weight。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '【说明】备用工号字段,目前未在该门店启用。 【示例】NULL(用于备用工号字段,目前未在该门店启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - job_num。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '【说明】前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。 【示例】31(用于前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_sort。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '【说明】评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。 【示例】0.0(评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '【说明】助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分。 【示例】0.0(用于助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '【说明】累计被评分次数。 【示例】0(用于累计被评分次数)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '【说明】个人简介文案,预留给助教自我介绍使用。 【示例】NULL(用于个人简介文案,预留给助教自我介绍使用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - introduce。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '【说明】助教个人视频介绍地址。 【示例】https://oss.ficoo.vip/cbb/userVideo/1753096246308/175309624630830.mp4(用于助教个人视频介绍地址)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - video_introduction_url。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '【说明】上层“分组 ID”预留字段(例如集团/事业部),本门店未使用。 【示例】0(用于上层“分组 ID”预留字段(例如集团/事业部),本门店未使用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '【说明】group_id 对应的名称,目前为空。 【示例】NULL(用于group_id 对应的名称,目前为空)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '【说明】门店名称,冗余字段,用于展示。 【示例】朗朗桌球(门店名称,冗余字段,用于展示)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - shop_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '【说明】2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现。 【示例】2(用于2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - charge_way。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_type。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - allow_cx。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_guaranteed。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - salary_grant_enabled。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '【说明】灯光控制状态,如 1=启用控制、2=不启用 或相反。 【示例】2(用于灯光控制状态,如 1=启用控制、2=不启用 或相反)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '【说明】在线状态。 【示例】1(用于在线状态)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - online_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '【说明】促销时段的单价,本门店未在账号表层面设置。 【示例】0.0(用于促销时段的单价,本门店未在账号表层面设置)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - cx_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '【说明】某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中)。 【示例】0.0(用于某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - pd_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '【说明】该助教最近一次服务的球台 ID。 【示例】0(用于该助教最近一次服务的球台 ID)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '【说明】最近服务球台名称(展示用)。 【示例】TV(用于最近服务球台名称(展示用))。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '【说明】人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织。 【示例】2947562271215109(用于人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '【说明】系统内部生成的序列号或排序标识,用于全局排序或迁移。 【示例】0(系统内部生成的序列号或排序标识,用于全局排序或迁移)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - serial_number。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_team_leader。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '【说明】1 × 49。 【示例】1(用于1 × 49)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - criticism_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_update_name IS '【说明】最近修改该账号配置的管理员名称。 【示例】管理员:郑丽珊(用于最近修改该账号配置的管理员名称)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_update_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - ding_talk_synced。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '【说明】门店灯控配置 ID,本门店未在助教账号维度启用。 【示例】0(用于门店灯控配置 ID,本门店未在助教账号维度启用)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_light_cfg_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '【说明】灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件。 【示例】NULL(用于灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_equipment_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '【说明】离职协议签署状态,类似上面。 【示例】0(用于离职协议签署状态,类似上面)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_accounts_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_accounts_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_accounts_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ levelname TEXT,
+ site_assistant_id BIGINT,
+ skill_id BIGINT,
+ skillname TEXT,
+ system_member_id BIGINT,
+ tablename TEXT,
+ tenant_member_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS 'ODS 原始明细表:助教服务流水。来源:export/test-json-doc/assistant_service_records.json;分析:assistant_service_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '【说明】本条助教流水记录的主键 ID(流水唯一标识)。 【示例】2957913441292165(用于本条助教流水记录的主键 ID(流水唯一标识))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '【说明】门店 ID,本数据中指“朗朗桌球”这一家门店。 【示例】2790685415443269(用于门店 ID,本数据中指“朗朗桌球”这一家门店)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '【说明】门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '【说明】球台 ID。 【示例】2793020259897413(用于球台 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '【说明】订单结算 ID,相当于“结账单号”的内部主键。 【示例】2957913171693253(用于订单结算 ID,相当于“结账单号”的内部主键)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '【说明】订单交易号,整个订单层面的编号。 【示例】2957784612605829(用于订单交易号,整个订单层面的编号)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '【说明】关联到“支付记录”的主键 ID。 【示例】0(用于关联到“支付记录”的主键 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '【说明】订单中“助教项目明细”的内部 ID。 【示例】2957788717240005(用于订单中“助教项目明细”的内部 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_type。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '【说明】助教姓名,如“何海婷”“胡敏”等。 【示例】何海婷(用于助教姓名,如“何海婷”“胡敏”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '【说明】助教编号,例如 "27"。 【示例】27(用于助教编号,例如 "27")。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantNo。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '【说明】助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。 【示例】10(用于助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_level。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.levelname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - levelName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_assistant_id IS '【说明】门店维度的助教 ID。 【示例】2946266869435205(用于门店维度的助教 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_id IS '【说明】助教服务“课程/技能”ID。 【示例】2790683529513797(用于助教服务“课程/技能”ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skillname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skillName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.system_member_id IS '【说明】系统级会员 ID(全集团统一 ID)。 【示例】0(用于系统级会员 ID(全集团统一 ID))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - system_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tablename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tableName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_member_id IS '【说明】商户维度会员 ID(门店/品牌内的会员主键)。 【示例】0(用于商户维度会员 ID(门店/品牌内的会员主键))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.user_id IS '【说明】助教对应的“用户账号 ID”(系统级用户)。 【示例】2946266868976453(用于助教对应的“用户账号 ID”(系统级用户))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '【说明】助教对外昵称,如“佳怡”“周周”“球球”等。 【示例】泡芙(用于助教对外昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】27-泡芙(名称字段,用于展示与辅助识别)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '【说明】助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。 【示例】NULL(用于助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '【说明】按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。 【示例】206.67(用于按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '【说明】台账记录的计时总秒数。 【示例】7592(用于台账记录的计时总秒数)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_count。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '【说明】助教服务 标准单价(通常是标价:每小时、每节课的单价)。 【示例】98.0(用于助教服务 标准单价(通常是标价:每小时、每节课的单价))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '【说明】台账层面记录的开始时间。 【示例】2025-11-09 21:18:18(用于台账层面记录的开始时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '【说明】台账层面的结束时间。 【示例】2025-11-09 23:24:50(用于台账层面的结束时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '【说明】收银员手动给予的减免金额(人工改价)。 【示例】0.0(用于收银员手动给予的减免金额(人工改价))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - manual_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '【说明】由会员卡折扣产生的优惠金额。 【示例】0.0(用于由会员卡折扣产生的优惠金额)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '【说明】由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。 【示例】0.0(用于由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '【说明】用于记录与助教结算的金额(平台预留的“成本/分成”字段)。 【示例】0.0(用于记录与助教结算的金额(平台预留的“成本/分成”字段))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '【说明】实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。 【示例】168.0(用于实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - projected_income。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '【说明】实际使用时长(秒)。 【示例】7592(用于实际使用时长(秒))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - real_use_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '【说明】计费秒数 / 应计收入对应的时间。 【示例】7560(用于计费秒数 / 应计收入对应的时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - income_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '【说明】助教实际开始服务时间。 【示例】2025-11-09 21:18:18(用于助教实际开始服务时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - start_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '【说明】最后一次使用(实际服务)时间。 【示例】2025-11-09 23:24:50(用于最后一次使用(实际服务)时间)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - last_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '【说明】这条助教流水记录创建时间(一般接近结算/下单时间)。 【示例】2025-11-09 23:25:11(用于这条助教流水记录创建时间(一般接近结算/下单时间))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_single_order。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_trash。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '【说明】废除原因(文本说明),例如“顾客取消”“录入错误”等。 【示例】NULL(用于废除原因(文本说明),例如“顾客取消”“录入错误”等)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_reason。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '【说明】提出废除申请的员工 ID(通常是操作员/管理员)。 【示例】0(用于提出废除申请的员工 ID(通常是操作员/管理员))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '【说明】废除申请人姓名。 【示例】NULL(用于废除申请人姓名)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '【说明】操作员 ID(录入/结算这条助教服务的员工)。 【示例】2790687322443013(用于操作员 ID(录入/结算这条助教服务的员工))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - operator_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '【说明】操作员姓名,与 operator_id 一起使用,便于直接阅读。 【示例】收银员:郑丽珊(用于操作员姓名,与 operator_id 一起使用,便于直接阅读)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - operator_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '【说明】关联的“营业员/销售员姓名”,用于提成归属。 【示例】NULL(关联的“营业员/销售员姓名”,用于提成归属)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '【说明】营业员用户 ID。 【示例】0(用于营业员用户 ID)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '【说明】助教所属“人事组织/部门 ID”。 【示例】2946266869336901(用于助教所属“人事组织/部门 ID”)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '【说明】加钟秒数,即在原有预约/服务基础上临时追加的时长。 【示例】0(用于加钟秒数,即在原有预约/服务基础上临时追加的时长)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - add_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '【说明】退钟秒数(取消加钟或提前结束退回的时间)。 【示例】0(用于退钟秒数(取消加钟或提前结束退回的时间))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - returns_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '【说明】综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。 【示例】0.0(用于综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '【说明】助教服务所在的球台名称(如 "A17"、"S1")。 【示例】0001-01-01 00:00:00(用于助教服务所在的球台名称(如 "A17"、"S1"))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '【说明】顾客对“技能表现”的评分(整数或打分等级)。 【示例】0(用于顾客对“技能表现”的评分(整数或打分等级))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '【说明】顾客对“服务态度”的评分。 【示例】0(用于顾客对“服务态度”的评分)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '【说明】累计评分总和(可能用于计算平均分),当前为 0。 【示例】0.0(累计评分总和(可能用于计算平均分),当前为 0)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '【说明】1 = 未评价/正常。 【示例】1(用于1 = 未评价/正常)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - grade_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '【说明】该条记录对应的评价次数(或该助教被评价次数快照)。 【示例】0(用于该条记录对应的评价次数(或该助教被评价次数快照))。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_not_responding。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_confirm。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - $。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_service_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_service_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】assistant_service_records.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS 'ODS 原始明细表:门店桌台主数据。来源:export/test-json-doc/site_tables_master.json;分析:site_tables_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '【说明】台桌主键 ID。 【示例】2791964216463493(用于台桌主键 ID)。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_tables_master.json - data.siteTables - site_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '【说明】门店名称快照,冗余字段,配合 site_id 使用。 【示例】朗朗桌球(用于门店名称快照,冗余字段,配合 site_id 使用)。 【JSON字段】site_tables_master.json - data.siteTables - siteName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '【说明】区域名称,用于前台展示和区域维度管理。 【示例】A区(区域名称,用于前台展示和区域维度管理)。 【JSON字段】site_tables_master.json - data.siteTables - areaName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '【说明】当前值:全部为 2。 【示例】2(用于当前值:全部为 2)。 【JSON字段】site_tables_master.json - data.siteTables - audit_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - charge_free。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '【说明】台桌配置的创建时间或最近一次创建/复制时间。 【示例】2025-07-15 17:52:54(用于台桌配置的创建时间或最近一次创建/复制时间)。 【JSON字段】site_tables_master.json - data.siteTables - create_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '【说明】台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。 【示例】0(台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯)。 【JSON字段】site_tables_master.json - data.siteTables - delay_lights_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】site_tables_master.json - data.siteTables - is_online_reservation。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - is_rest_area。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】site_tables_master.json - data.siteTables - light_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '【说明】小程序二维码 URL。 【示例】2(用于小程序二维码 URL)。 【JSON字段】site_tables_master.json - data.siteTables - only_allow_groupon。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '【说明】订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。 【示例】0(用于订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费))。 【JSON字段】site_tables_master.json - data.siteTables - order_delay_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '【说明】当前值:全部为 1。 【示例】1(用于当前值:全部为 1)。 【JSON字段】site_tables_master.json - data.siteTables - self_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】site_tables_master.json - data.siteTables - show_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '【说明】门店维度的“台桌区域 ID”。 【示例】2791963794329671(用于门店维度的“台桌区域 ID”)。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '【说明】table_status 的中文名称,仅为展示用途。 【示例】空闲中(用于table_status 的中文名称,仅为展示用途)。 【JSON字段】site_tables_master.json - data.siteTables - tableStatusName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '【说明】台呢使用周期阈值,例如达到某个秒数后提醒更换。 【示例】0(用于台呢使用周期阈值,例如达到某个秒数后提醒更换)。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_Cycle。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】1863727(时间字段,用于记录业务时间点/发生时间。)。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '【说明】台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。 【示例】A1(台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段)。 【JSON字段】site_tables_master.json - data.siteTables - table_name。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '【说明】设计上应为“台的基础单价”字段(例如按小时或按局单价)。 【示例】0.0(用于设计上应为“台的基础单价”字段(例如按小时或按局单价))。 【JSON字段】site_tables_master.json - data.siteTables - table_price。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '【说明】台当前运行状态,真实反映某一时刻台的占用/暂停情况。 【示例】1(用于台当前运行状态,真实反映某一时刻台的占用/暂停情况)。 【JSON字段】site_tables_master.json - data.siteTables - table_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '【说明】临时点灯时长(秒),例如手动临时开灯一段时间。 【示例】0(用于临时点灯时长(秒),例如手动临时开灯一段时间)。 【JSON字段】site_tables_master.json - data.siteTables - temporary_light_second。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】site_tables_master.json - data.siteTables - virtual_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】site_tables_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/site_tables_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】site_tables_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】site_tables_master.json - data.siteTables - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS 'ODS 原始明细表:台费折扣记录。来源:export/test-json-doc/table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '【说明】台费打折 / 调整流水主键 ID。 【示例】2957913441881989(用于台费打折 / 调整流水主键 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '【说明】门店 ID,本批数据全部为同一家门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本批数据全部为同一家门店(朗朗桌球))。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '【说明】门店信息快照,用于报表时直接读取,无需再联门店档案。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(门店信息快照,用于报表时直接读取,无需再联门店档案)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '【说明】台桌 ID。 【示例】2793020259897413(用于台桌 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '【说明】折扣发生时,对应台桌的配置信息快照。 【示例】{"id": 2793020259897413, "tenant_id": 2790683160709957, "tenant_name": "", "siteName": "", "table_name": "S1", "site_ta…(用于折扣发生时,对应台桌的配置信息快照)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tableProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '【说明】租户维度的“台桌区域 ID”。 【示例】2791961347968901(用于租户维度的“台桌区域 ID”)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '【说明】文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。 【示例】1(用于文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - adjust_type。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】148.15(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '【说明】这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。 【示例】1(用于这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '【说明】设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。 【示例】NULL(设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '【说明】打折/调账申请人 ID。 【示例】2790687322443013(用于打折/调账申请人 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '【说明】申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。 【示例】收银员:郑丽珊(用于申请人姓名(带角色描述),为 applicant_id 的冗余显示字段)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '【说明】实际执行调账操作的操作员 ID。 【示例】2790687322443013(用于实际执行调账操作的操作员 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '【说明】操作员姓名。 【示例】收银员:郑丽珊(用于操作员姓名)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '【说明】结算单/小票 ID。 【示例】2957913171693253(用于结算单/小票 ID)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '【说明】订单交易号。 【示例】2957784612605829(用于订单交易号)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '【说明】台费调整记录的创建时间,即打折操作被执行的时间戳。 【示例】2025-11-09 23:25:11(用于台费调整记录的创建时间,即打折操作被执行的时间戳)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_discount_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_discount_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】table_fee_discount_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS 'ODS 原始明细表:台费流水。来源:export/test-json-doc/table_fee_transactions.json;分析:table_fee_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '【说明】台费流水记录主键(事实表主键)。 【示例】2957924029058885(用于台费流水记录主键(事实表主键))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '【说明】门店 ID,本次数据全部来自同一门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本次数据全部来自同一门店(朗朗桌球))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '【说明】门店内“台桌区域” ID(站在门店物理布局的角度)。 【示例】2791963794329671(用于门店内“台桌区域” ID(站在门店物理布局的角度))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '【说明】台桌区域的名称,用于门店表现和区域统计。 【示例】A区(台桌区域的名称,用于门店表现和区域统计)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '【说明】租户维度的台桌区域 ID(品牌层面的同一类区域)。 【示例】2791960001957765(用于租户维度的台桌区域 ID(品牌层面的同一类区域))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '【说明】订单交易号,是整笔订单的主编号。 【示例】2957858167230149(用于订单交易号,是整笔订单的主编号)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '【说明】订单支付记录 ID。 【示例】0(用于订单支付记录 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '【说明】结算单号/结账 ID,对应一次结账操作。 【示例】2957922914357125(用于结算单号/结账 ID,对应一次结账操作)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '【说明】台号名称,实际展示给员工/顾客看的桌台编号。 【示例】A17(用于台号名称,实际展示给员工/顾客看的桌台编号)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '【说明】按单价与计费时长计算出的原始应收台费金额。 【示例】48.0(用于按单价与计费时长计算出的原始应收台费金额)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '【说明】台账记录的计费秒数,计费用秒数(应收时长)。 【示例】3600(用于台账记录的计费秒数,计费用秒数(应收时长))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '【说明】台费结算时设置的 每小时单价/计费单价。 【示例】48.0(用于台费结算时设置的 每小时单价/计费单价)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '【说明】台账上的计费起始时间。 【示例】2025-11-09 22:28:57(用于台账上的计费起始时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '【说明】台账上的计费结束时间。 【示例】2025-11-09 23:28:57(用于台账上的计费结束时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '【说明】台开始使用的时间(实际开台时间)。 【示例】2025-11-09 22:28:57(用于台开始使用的时间(实际开台时间))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - start_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '【说明】最后使用/操作时间。 【示例】2025-11-09 23:28:57(用于最后使用/操作时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - last_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '【说明】实际使用的总秒数(系统真实统计的使用时长)。 【示例】3600(用于实际使用的总秒数(系统真实统计的使用时长))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_use_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '【说明】台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。 【示例】0.0(用于台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_charge_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '【说明】加钟秒数,在原有使用基础上追加的时长。 【示例】0(用于加钟秒数,在原有使用基础上追加的时长)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - add_clock_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '【说明】调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。 【示例】0.0(调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - adjust_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '【说明】由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。 【示例】48.0(用于由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - coupon_promotion_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '【说明】由会员权益产生的优惠金额,例如会员折扣、会员价等。 【示例】0.0(用于由会员权益产生的优惠金额,例如会员折扣、会员价等)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '【说明】由储值卡、次卡等“卡内余额”抵扣的金额。 【示例】0.0(用于由储值卡、次卡等“卡内余额”抵扣的金额)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - used_card_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '【说明】管理费字段,用于未来支持“台费附加管理费/服务费”的功能。 【示例】0.0(管理费字段,用于未来支持“台费附加管理费/服务费”的功能)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - mgmt_fee。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '【说明】门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。 【示例】0.0(门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - service_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '【说明】各种附加费用(如管理费、服务费)合计值。 【示例】0.0(用于各种附加费用(如管理费、服务费)合计值)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - fee_total。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '【说明】门店/租户内的会员 ID。 【示例】0(用于门店/租户内的会员 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '【说明】操作员 ID,负责开台/结账的员工账号 ID。 【示例】2790687322443013(用于操作员 ID,负责开台/结账的员工账号 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '【说明】操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。 【示例】收银员:郑丽珊(用于操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '【说明】业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。 【示例】NULL(用于业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '【说明】营业员所属机构/部门 ID。 【示例】0(用于营业员所属机构/部门 ID)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '【说明】营业员的用户 ID(与 salesman_name 搭配)。 【示例】0(用于营业员的用户 ID(与 salesman_name 搭配))。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '【说明】这条台费流水记录的创建时间,通常接近结账时间。 【示例】2025-11-09 23:35:57(用于这条台费流水记录的创建时间,通常接近结账时间)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - $。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】table_fee_transactions.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS 'ODS 原始明细表:商品库存变动流水。来源:export/test-json-doc/goods_stock_movements.json;分析:goods_stock_movements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '【说明】门店某个“商品库存记录”的主键 ID。 【示例】2957911857581957(用于门店某个“商品库存记录”的主键 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteGoodsStockId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - tenantId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '【说明】门店维度的商品 ID。 【示例】2793026183532613(用于门店维度的商品 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '【说明】商品名称。 【示例】阿萨姆(用于商品名称)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - goodsSecondCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '【说明】库存计量单位。 【示例】瓶(用于库存计量单位)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - unit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '【说明】商品单价(单位金额)。 【示例】8.0(用于商品单价(单位金额))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - price。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '【说明】1:89 条。 【示例】1(用于1:89 条)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - stockType。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '【说明】本次库存数量变化值。 【示例】-1(用于本次库存数量变化值)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - changeNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '【说明】变动前(这次出入库之前)的库存数量。 【示例】28(用于变动前(这次出入库之前)的库存数量)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - startNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '【说明】变动后(出入库之后)的库存数量。 【示例】27(用于变动后(出入库之后)的库存数量)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - endNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '【说明】辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。 【示例】0(用于辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - changeNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '【说明】辅助计量单位的起始库存(例如件/箱等第二单位)。 【示例】0(用于辅助计量单位的起始库存(例如件/箱等第二单位))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - startNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '【说明】辅助单位的变动后库存,同样未启用。 【示例】0(用于辅助单位的变动后库存,同样未启用)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - endNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '【说明】备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。 【示例】NULL(备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”))。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - remark。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '【说明】执行此次库存变动的操作人。 【示例】收银员:郑丽珊(用于执行此次库存变动的操作人)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - operatorName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '【说明】这条库存变动记录的创建时间,即发生库存变更的时间点。 【示例】2025-11-09 23:23:34(用于这条库存变动记录的创建时间,即发生库存变更的时间点)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - createTime。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_movements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_movements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】goods_stock_movements.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】goods_stock_movements.json - data.queryDeliveryRecordsList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS 'ODS 原始明细表:商品分类树。来源:export/test-json-doc/stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '【说明】分类节点主键 ID(在商品分类维度中的唯一标识)。 【示例】2790683528350533(用于分类节点主键 ID(在商品分类维度中的唯一标识))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '【说明】分类名称(实际业务分类名称)。 【示例】槟榔(用于分类名称(实际业务分类名称))。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - category_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别。)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - alias_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '【说明】父级分类 ID。 【示例】0(用于父级分类 ID)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - pid。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '【说明】业务大类名称。 【示例】槟榔(用于业务大类名称)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - business_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '【说明】业务大类 ID。 【示例】2790683528317766(用于业务大类 ID)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '【说明】是否启用“营业员”或“导购提成”相关的功能开关。 【示例】2(用于是否启用“营业员”或“导购提成”相关的功能开关)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - open_salesman。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '【说明】子分类数组。 【示例】[{"id": 2790683528350534, "tenant_id": 2790683160709957, "category_name": "槟榔", "alias_name": "", "pid": 27906835283505…(用于子分类数组)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - categoryBoxes。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '【说明】分类的排序序号,用于前端展示顺序的控制。 【示例】1(分类的排序序号,用于前端展示顺序的控制)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - sort。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '【说明】本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1。 【示例】1(用于本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】stock_goods_category_tree.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/stock_goods_category_tree.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】stock_goods_category_tree.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS 'ODS 原始明细表:商品库存汇总。来源:export/test-json-doc/goods_stock_summary.json;分析:goods_stock_summary-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '【说明】门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识。 【示例】2791953867886725(用于门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识)。 【JSON字段】goods_stock_summary.json - $ - siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '【说明】商品名称,冗余于门店商品档案的 goods_name。 【示例】东方树叶(用于商品名称,冗余于门店商品档案的 goods_name)。 【JSON字段】goods_stock_summary.json - $ - goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '【说明】商品的计量单位(售卖单位)。 【示例】瓶(用于商品的计量单位(售卖单位))。 【JSON字段】goods_stock_summary.json - $ - goodsUnit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '【说明】一级商品分类 ID。 【示例】2790683528350539(用于一级商品分类 ID)。 【JSON字段】goods_stock_summary.json - $ - goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '【说明】二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类。 【示例】2790683528350540(用于二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类)。 【JSON字段】goods_stock_summary.json - $ - goodsCategorySecondId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '【说明】一级分类名称,属于冗余字段,用于直接展示。 【示例】酒水(一级分类名称,属于冗余字段,用于直接展示)。 【JSON字段】goods_stock_summary.json - $ - categoryName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '【说明】查询区间 起始时刻 的库存数量(期初库存)。 【示例】165(用于查询区间 起始时刻 的库存数量(期初库存))。 【JSON字段】goods_stock_summary.json - $ - rangeStartStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '【说明】查询区间 结束时刻 的库存数量(期末库存)。 【示例】118(用于查询区间 结束时刻 的库存数量(期末库存))。 【JSON字段】goods_stock_summary.json - $ - rangeEndStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '【说明】查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等。 【示例】450(用于查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等)。 【JSON字段】goods_stock_summary.json - $ - rangeIn。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '【说明】查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售)。 【示例】-497(用于查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售))。 【JSON字段】goods_stock_summary.json - $ - rangeOut。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '【说明】查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等)。 【示例】488(用于查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等))。 【JSON字段】goods_stock_summary.json - $ - rangeSale。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '【说明】查询区间内,该商品销售的 金额小计(按商品维度汇总)。 【示例】3904.0(用于查询区间内,该商品销售的 金额小计(按商品维度汇总))。 【JSON字段】goods_stock_summary.json - $ - rangeSaleMoney。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '【说明】查询区间内的 盘点调整净变动量(盘盈–盘亏)。 【示例】0(用于查询区间内的 盘点调整净变动量(盘盈–盘亏))。 【JSON字段】goods_stock_summary.json - $ - rangeInventory。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '【说明】导出时刻的实时库存数量。 【示例】118(用于导出时刻的实时库存数量)。 【JSON字段】goods_stock_summary.json - $ - currentStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_summary.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_summary.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】goods_stock_summary.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】goods_stock_summary.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS 'ODS 原始明细表:支付流水。来源:export/test-json-doc/payment_transactions.json;分析:payment_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '【说明】支付流水记录的主键 ID。 【示例】2957924026486597(用于支付流水记录的主键 ID)。 【JSON字段】payment_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '【说明】支付记录所属的门店 ID。 【示例】2790685415443269(用于支付记录所属的门店 ID)。 【JSON字段】payment_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '【说明】门店信息快照,与其他 JSON 中的 siteProfile 结构一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,与其他 JSON 中的 siteProfile 结构一致)。 【JSON字段】payment_transactions.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '【说明】表示“这条支付记录关联的业务类型”。 【示例】2(用于表示“这条支付记录关联的业务类型”)。 【JSON字段】payment_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '【说明】关联业务记录的主键 ID(按 relate_type 不同指向不同表)。 【示例】2957922914357125(用于关联业务记录的主键 ID(按 relate_type 不同指向不同表))。 【JSON字段】payment_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '【说明】本条支付流水的“支付金额”,单位为元。 【示例】10.0(用于本条支付流水的“支付金额”,单位为元)。 【JSON字段】payment_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '【说明】支付状态枚举字段。 【示例】2(用于支付状态枚举字段)。 【JSON字段】payment_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '【说明】实际支付完成时间(支付状态变为成功的时间戳)。 【示例】2025-11-09 23:35:57(用于实际支付完成时间(支付状态变为成功的时间戳))。 【JSON字段】payment_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '【说明】支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳)。 【示例】2025-11-09 23:35:57(用于支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳))。 【JSON字段】payment_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '【说明】支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种。 【示例】4(用于支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种)。 【JSON字段】payment_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '【说明】每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一)。 【示例】0(用于每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一))。 【JSON字段】payment_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】payment_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/payment_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】payment_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】payment_transactions.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS 'ODS 原始明细表:退款流水。来源:export/test-json-doc/refund_transactions.json;分析:refund_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '【说明】本条 退款流水 的唯一 ID。 【示例】2955202296416389(用于本条 退款流水 的唯一 ID)。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '【说明】租户/品牌 ID,全系统维度标识该商户。 【示例】2790683160709957(用于租户/品牌 ID,全系统维度标识该商户)。 【JSON字段】refund_transactions.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '【说明】租户(商户)名称。 【示例】朗朗桌球(用于租户(商户)名称)。 【JSON字段】refund_transactions.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】refund_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '【说明】门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致)。 【JSON字段】refund_transactions.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '【说明】本退款对应的“业务类型”。 【示例】5(用于本退款对应的“业务类型”)。 【JSON字段】refund_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '【说明】本次退款关联的业务 ID。 【示例】2955078219057349(用于本次退款关联的业务 ID)。 【JSON字段】refund_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】refund_transactions.json - $ - pay_sn。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '【说明】本次退款的 资金变动金额。 【示例】-5000.0(用于本次退款的 资金变动金额)。 【JSON字段】refund_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '【说明】设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用。 【示例】0.0(用于设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用)。 【JSON字段】refund_transactions.json - $ - refund_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '【说明】舍入金额/抹零金额。 【示例】0.0(用于舍入金额/抹零金额)。 【JSON字段】refund_transactions.json - $ - round_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '【说明】退款在支付渠道层面实际发生的时间。 【示例】2025-11-08 01:27:16(用于退款在支付渠道层面实际发生的时间)。 【JSON字段】refund_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '【说明】本条退款流水在系统内创建时间。 【示例】2025-11-08 01:27:16(用于本条退款流水在系统内创建时间)。 【JSON字段】refund_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】4(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - pay_terminal。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '【说明】支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。 【示例】0(用于支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键)。 【JSON字段】refund_transactions.json - $ - pay_config_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】refund_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '【说明】当前:全部 0。 【示例】0(用于当前:全部 0)。 【JSON字段】refund_transactions.json - $ - online_pay_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '【说明】第三方支付渠道对本次退款收取的手续费。 【示例】0.0(用于第三方支付渠道对本次退款收取的手续费)。 【JSON字段】refund_transactions.json - $ - channel_fee。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '【说明】支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。 【示例】NULL(用于支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等)。 【JSON字段】refund_transactions.json - $ - channel_payer_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '【说明】第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。 【示例】NULL(用于第三方支付平台的交易号(如微信支付单号、支付宝交易号等))。 【JSON字段】refund_transactions.json - $ - channel_pay_no。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '【说明】租户内部的会员 ID(对应会员档案中的某个主键)。 【示例】0(用于租户内部的会员 ID(对应会员档案中的某个主键))。 【JSON字段】refund_transactions.json - $ - member_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '【说明】关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。 【示例】0(用于关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡))。 【JSON字段】refund_transactions.json - $ - member_card_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '【说明】收银点 ID,例如前台 1、前台 2、自助机等。 【示例】0(用于收银点 ID,例如前台 1、前台 2、自助机等)。 【JSON字段】refund_transactions.json - $ - cashier_point_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '【说明】执行该退款操作的操作员 ID。 【示例】0(用于执行该退款操作的操作员 ID)。 【JSON字段】refund_transactions.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '【说明】当前:全部 2。 【示例】2(用于当前:全部 2)。 【JSON字段】refund_transactions.json - $ - action_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '【说明】当前:全部 1。 【示例】1(用于当前:全部 1)。 【JSON字段】refund_transactions.json - $ - check_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】refund_transactions.json - $ - is_revoke。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】refund_transactions.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '【说明】涉及会员储值卡退款时,暂时冻结的余额金额。 【示例】0.0(用于涉及会员储值卡退款时,暂时冻结的余额金额)。 【JSON字段】refund_transactions.json - $ - balance_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '【说明】与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。 【示例】0.0(用于与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关)。 【JSON字段】refund_transactions.json - $ - card_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】refund_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/refund_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】refund_transactions.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】refund_transactions.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS 'ODS 原始明细表:平台券核销/使用记录。来源:export/test-json-doc/platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '【说明】本条平台验券记录在本系统内的主键 ID。 【示例】2957929042218501(用于本条平台验券记录在本系统内的主键 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '【说明】平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID)。 【示例】7570689090418149418(用于平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID))。 【JSON字段】platform_coupon_redemption_records.json - $ - verify_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '【说明】平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID)。 【示例】5008024789379597447(用于平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID))。 【JSON字段】platform_coupon_redemption_records.json - $ - certificate_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '【说明】券码,顾客出示的团购券密码/编号。 【示例】0102701209726(用于券码,顾客出示的团购券密码/编号)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_code。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '【说明】团购券产品名称(即第三方平台上向顾客展示的名称)。 【示例】【全天可用】中八桌球一小时(A区)(用于团购券产品名称(即第三方平台上向顾客展示的名称))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '【说明】券来源渠道(第三方平台渠道编号)。 【示例】1(用于券来源渠道(第三方平台渠道编号))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_channel。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '【说明】团购券类型。 【示例】1(用于团购券类型)。 【JSON字段】platform_coupon_redemption_records.json - $ - groupon_type。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体。)。 【JSON字段】platform_coupon_redemption_records.json - $ - group_package_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '【说明】顾客在第三方平台上实际支付的价格(团购售价)。 【示例】29.9(用于顾客在第三方平台上实际支付的价格(团购售价))。 【JSON字段】platform_coupon_redemption_records.json - $ - sale_price。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '【说明】券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”)。 【示例】48.0(用于券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_money。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '【说明】券附带的“免费时长”字段(例如送多少分钟台费)。 【示例】0(用于券附带的“免费时长”字段(例如送多少分钟台费))。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_free_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_cover。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】617547ec-9697-4f58-a700-b30a49e88904||CgYIASAHKAESLgos9ZhHDryhHb0z3RpdBZ0dVoaQbkldBcx/XTXPV8Te+9SEqYOa7aDp8nbKOpsaAA==(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_remark。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '【说明】值 1:198 条。 【示例】1(用于值 1:198 条)。 【JSON字段】platform_coupon_redemption_records.json - $ - use_status。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '【说明】券被核销/使用的业务时间。 【示例】2025-11-09 23:41:04(用于券被核销/使用的业务时间)。 【JSON字段】platform_coupon_redemption_records.json - $ - consume_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '【说明】验券记录在本系统中创建的时间(记录入库时间)。 【示例】2025-11-09 23:41:03(用于验券记录在本系统中创建的时间(记录入库时间))。 【JSON字段】platform_coupon_redemption_records.json - $ - create_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '【说明】另一个层次的团购产品 ID。 【示例】1345108507(用于另一个层次的团购产品 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '【说明】渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键。 【示例】1128411555(用于渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键)。 【JSON字段】platform_coupon_redemption_records.json - $ - channel_deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - site_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '【说明】门店内部的订单 ID(平台券核销时对应的店内订单)。 【示例】2957929043037702(用于门店内部的订单 ID(平台券核销时对应的店内订单))。 【JSON字段】platform_coupon_redemption_records.json - $ - site_order_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '【说明】使用券的球台 ID。 【示例】2793001904918661(用于使用券的球台 ID)。 【JSON字段】platform_coupon_redemption_records.json - $ - table_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '【说明】商户/租户 ID(品牌级别)。 【示例】2790683160709957(用于商户/租户 ID(品牌级别))。 【JSON字段】platform_coupon_redemption_records.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '【说明】操作员 ID(执行验券操作的收银员/员工)。 【示例】2790687322443013(用于操作员 ID(执行验券操作的收银员/员工))。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '【说明】操作员姓名,例如 "收银员:郑丽珊"。 【示例】收银员:郑丽珊(用于操作员姓名,例如 "收银员:郑丽珊")。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '【说明】把平台验券记录挂到本门店的一条订单上。 【示例】0(用于把平台验券记录挂到本门店的一条订单上)。 【JSON字段】platform_coupon_redemption_records.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】platform_coupon_redemption_records.json - $ - siteProfile。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】platform_coupon_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/platform_coupon_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】platform_coupon_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】platform_coupon_redemption_records.json - $ - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ out_goods_id TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS 'ODS 原始明细表:租户商品主数据。来源:export/test-json-doc/tenant_goods_master.json;分析:tenant_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '【说明】商品档案主键 ID,唯一标识一条商品。 【示例】2791925230096261(用于商品档案主键 ID,唯一标识一条商品)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '【说明】商品名称(前台展示名称)。 【示例】东方树叶(用于商品名称(前台展示名称))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '【说明】商品条码(EAN 等),目前未维护。 【示例】NULL(用于商品条码(EAN 等),目前未维护)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '【说明】商品一级分类名称(业务可读)。 【示例】饮料(用于商品一级分类名称(业务可读))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - categoryName。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '【说明】计量单位。 【示例】瓶(用于计量单位)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - unit。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '【说明】商品内部编码(自定义货号/系统货号)。 【示例】1(用于商品内部编码(自定义货号/系统货号))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_number。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.out_goods_id IS '【说明】外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等)。 【示例】0(用于外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - out_goods_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '【说明】商品状态(上架/下架等)。 【示例】1(用于商品状态(上架/下架等))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '【说明】销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。 【示例】1(用于销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '【说明】是否允许参与折扣/打折。 【示例】1(用于是否允许参与折扣/打折)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '【说明】是否启用库存管理。 【示例】1(用于是否启用库存管理)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '【说明】是否在当前门店启用/上架。 【示例】false(用于是否在当前门店启用/上架)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - isInSite。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '【说明】成本价格。 【示例】0.0(用于成本价格)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】1(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '【说明】商品标价 / 售价(标准销售单价)。 【示例】8.0(用于商品标价 / 售价(标准销售单价))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - market_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '【说明】该商品允许售卖的最低价格(底价)。 【示例】0.0(用于该商品允许售卖的最低价格(底价))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '【说明】普通销售提成比例或提成金额的配置字段。 【示例】0(用于普通销售提成比例或提成金额的配置字段)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - common_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '【说明】积分销售提成/积分赠送规则相关配置。 【示例】0(用于积分销售提成/积分赠送规则相关配置)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - point_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '【说明】拼音首字母/助记码。 【示例】DFSY,DFSX(用于拼音首字母/助记码)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '【说明】与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。 【示例】["10000028"](用于与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodityCode。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '【说明】商品编码(通常为对外商品编码或条码)。 【示例】10000028(用于商品编码(通常为对外商品编码或条码))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '【说明】商品封面图片 URL 地址。 【示例】https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(用于商品封面图片 URL 地址)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '【说明】供应商 ID,用于关联到供应商档案。 【示例】0(供应商 ID,用于关联到供应商档案)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - supplier_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '【说明】商品备注名/别名,通常用来配置简写或特殊显示名称。 【示例】NULL(用于商品备注名/别名,通常用来配置简写或特殊显示名称)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - remark_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '【说明】商品档案创建时间。 【示例】2025-07-15 17:13:15(用于商品档案创建时间)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - create_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '【说明】商品档案最近一次修改时间。 【示例】2025-10-29 23:51:38(用于商品档案最近一次修改时间)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - update_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - $。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】tenant_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/tenant_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】tenant_goods_master.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS 'ODS 原始明细表:团购套餐主数据。来源:export/test-json-doc/group_buy_packages.json;分析:group_buy_packages-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '【说明】门店侧套餐 ID,本文件内部的主键。 【示例】2939215004469573(用于门店侧套餐 ID,本文件内部的主键)。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '【说明】“上层套餐 ID” 或“总部/系统级套餐 ID”。 【示例】1814707240811572(用于“上层套餐 ID” 或“总部/系统级套餐 ID”)。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '【说明】团购套餐名称,用于前台展示和核销界面。 【示例】早场特惠一小时(团购套餐名称,用于前台展示和核销界面)。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '【说明】语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。 【示例】0.0(用于语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格))。 【JSON字段】group_buy_packages.json - data.packageCouponList - selling_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '【说明】券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。 【示例】0.0(用于券面值或内部结算面值,表示该套餐在门店侧对应的金额额度)。 【JSON字段】group_buy_packages.json - data.packageCouponList - coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '【说明】预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。 【示例】0(用于预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码))。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_info。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '【说明】套餐开始生效的日期时间。 【示例】2025-10-27 00:00:00(用于套餐开始生效的日期时间)。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '【说明】套餐失效的日期时间(到这个时间点后不可使用)。 【示例】2026-10-28 00:00:00(用于套餐失效的日期时间(到这个时间点后不可使用))。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '【说明】每日可用起始时间点(第一段)。 【示例】00:00:00(用于每日可用起始时间点(第一段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '【说明】每日可用的结束时间点(第一段)。 【示例】1.00:00:00(用于每日可用的结束时间点(第一段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '【说明】附加可用时间段的起始时间(第二段)。 【示例】00:00:00(用于附加可用时间段的起始时间(第二段))。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '【说明】附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。 【示例】1.00:00:00(用于附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用)。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '【说明】套餐内包含的时长(秒)。 【示例】3600(用于套餐内包含的时长(秒))。 【JSON字段】group_buy_packages.json - data.packageCouponList - duration。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '【说明】可使用次数上限。 【示例】9999999(用于可使用次数上限)。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '【说明】一般用于文字描述可用日期范围(例如“周一至周五”)。 【示例】NULL(一般用于文字描述可用日期范围(例如“周一至周五”))。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_range。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '【说明】原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。 【示例】0(用于原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '【说明】套餐适用的“门店台区名称”,用于显示和筛选。 【示例】A区(套餐适用的“门店台区名称”,用于显示和筛选)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '【说明】用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。 【示例】NULL(用于用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制)。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '【说明】与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。 【示例】0(与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择)。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '【说明】实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。 【示例】2791960001957765(用于实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围)。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '【说明】门店名称。 【示例】朗朗桌球(用于门店名称)。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '【说明】原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。 【示例】0(用于原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置)。 【JSON字段】group_buy_packages.json - data.packageCouponList - card_type_ids。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_packages.json - data.packageCouponList - system_group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '【说明】内部业务子类型,具体含义需要结合系统文档。 【示例】2(用于内部业务子类型,具体含义需要结合系统文档)。 【JSON字段】group_buy_packages.json - data.packageCouponList - type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '【说明】1:13 条。 【示例】1(用于1:13 条)。 【JSON字段】group_buy_packages.json - data.packageCouponList - effective_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '【说明】启用状态。 【示例】1(用于启用状态)。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_enabled。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】group_buy_packages.json - data.packageCouponList - max_selectable_categories。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '【说明】1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。 【示例】1(用于1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等)。 【JSON字段】group_buy_packages.json - data.packageCouponList - area_tag_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '【说明】创建人信息,一般包含“角色:姓名”。 【示例】店长:郑丽珊(用于创建人信息,一般包含“角色:姓名”)。 【JSON字段】group_buy_packages.json - data.packageCouponList - creator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '【说明】该套餐在系统中创建的时间。 【示例】2025-10-27 18:24:09(用于该套餐在系统中创建的时间)。 【JSON字段】group_buy_packages.json - data.packageCouponList - create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_packages.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_packages.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】group_buy_packages.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】group_buy_packages.json - data.packageCouponList - $。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS 'ODS 原始明细表:团购核销记录。来源:export/test-json-doc/group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '【说明】本条“团购套餐流水”记录的 主键 ID。 【示例】2957924029615941(用于本条“团购套餐流水”记录的 主键 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '【说明】门店 ID,与其它 JSON 中一致。 【示例】2790685415443269(用于门店 ID,与其它 JSON 中一致)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '【说明】门店名称,冗余展示用。 【示例】朗朗桌球(用于门店名称,冗余展示用)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - siteName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '【说明】本次使用券所关联的 球台名称/台号。 【示例】A17(用于本次使用券所关联的 球台名称/台号)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '【说明】该球台所属的 台区名称。 【示例】A区(用于该球台所属的 台区名称)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableAreaName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '【说明】租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。 【示例】2791960001957765(用于租户级台区分组 ID,表示当前使用券的台桌所属的区域组合)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '【说明】订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。 【示例】2957858167230149(用于订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '【说明】结算单 ID(小票结账主键)。 【示例】2957922914357125(用于结算单 ID(小票结账主键))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '【说明】指向支付记录表中的支付流水 ID。 【示例】0(用于指向支付记录表中的支付流水 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '【说明】订单中“券使用记录”的 ID。 【示例】2957858168229573(用于订单中“券使用记录”的 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_channel。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '【说明】团购券券码,核销时扫描/录入的字符串。 【示例】0107892475999(用于团购券券码,核销时扫描/录入的字符串)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_code。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '【说明】本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。 【示例】48.0(用于本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '【说明】平台/上游系统中的券记录主键 ID,“券来源 ID”。 【示例】2957858168229573(用于平台/上游系统中的券记录主键 ID,“券来源 ID”)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_origin_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '【说明】台费侧关联的“团购项目名称”(记账名)。 【示例】全天A区中八一小时(用于台费侧关联的“团购项目名称”(记账名))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '【说明】团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。 【示例】NULL(用于团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '【说明】本次券实际冲抵台费的金额。 【示例】48.0(用于本次券实际冲抵台费的金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '【说明】按此次优惠实际计算的“核销秒数”。 【示例】3600(用于按此次优惠实际计算的“核销秒数”)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '【说明】对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。 【示例】29.9(用于对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '【说明】流水状态。 【示例】1(用于流水状态)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '【说明】本次结算中该球台总计计费的秒数(整台的台费计费时间)。 【示例】3600(用于本次结算中该球台总计计费的秒数(整台的台费计费时间))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_charge_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '【说明】团购/促销活动 ID。 【示例】2957858166460101(用于团购/促销活动 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_activity_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '【说明】团购套餐定义 ID。 【示例】2798727423528005(用于团购套餐定义 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '【说明】团购套餐定义的“标准时长”(券本身标称的可用时长)。 【示例】3600(用于团购套餐定义的“标准时长”(券本身标称的可用时长))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '【说明】优惠类型。 【示例】1(用于优惠类型)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - offer_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '【说明】分摊到“助教服务”的促销金额。 【示例】0.0(用于分摊到“助教服务”的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '【说明】进一步细分助教服务的促销金额。 【示例】0.0(用于进一步细分助教服务的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '【说明】本次券使用中,分摊到“台费服务费”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“台费服务费”部分的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '【说明】本次券使用中,分摊到“商品”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“商品”部分的促销金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goods_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '【说明】来自“充值类优惠”的分摊金额(例如储值赠送部分)。 【示例】0.0(用于来自“充值类优惠”的分摊金额(例如储值赠送部分))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - recharge_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '【说明】本次促销中,属于“奖励金/积分抵扣”的金额。 【示例】0.0(用于本次促销中,属于“奖励金/积分抵扣”的金额)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - reward_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '【说明】商品规格价格,用于商品类促销分摊时使用。 【示例】0.0(商品规格价格,用于商品类促销分摊时使用)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goodsOptionPrice。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '【说明】营业员姓名。 【示例】NULL(用于营业员姓名)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '【说明】营业员所属组织 ID。 【示例】0(用于营业员所属组织 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '【说明】营业员角色 ID。 【示例】0(用于营业员角色 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '【说明】营业员/业务员用户 ID。 【示例】0(用于营业员/业务员用户 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '【说明】执行本次核销/结算操作的 操作员 ID。 【示例】2790687322443013(用于执行本次核销/结算操作的 操作员 ID)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '【说明】操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。 【示例】收银员:郑丽珊(用于操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '【说明】是否单独作为一条订单行。 【示例】1(用于是否单独作为一条订单行)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '【说明】本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。 【示例】2025-11-09 23:35:57(用于本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近))。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - $。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】group_buy_redemption_records.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS 'ODS 原始明细表:结算小票明细。来源:export/test-json-doc/settlement_ticket_details.json;分析:settlement_ticket_details-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '【说明】结算单 ID(和顶层字段相同,再次冗余)。 【示例】2957922914357125(用于结算单 ID(和顶层字段相同,再次冗余))。 【JSON字段】settlement_ticket_details.json - $ - orderSettleId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '【说明】本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。 【示例】NULL(用于本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等))。 【JSON字段】settlement_ticket_details.json - $ - actualPayment。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '【说明】人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计。 【示例】NULL(用于人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计)。 【JSON字段】settlement_ticket_details.json - $ - adjustAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '【说明】针对“助教项目”的人工减免金额汇总(整单维度)。 【示例】NULL(用于针对“助教项目”的人工减免金额汇总(整单维度))。 【JSON字段】settlement_ticket_details.json - $ - assistantManualDiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '【说明】本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。 【示例】NULL(用于本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额))。 【JSON字段】settlement_ticket_details.json - $ - balanceAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '【说明】本单结算操作员名称(带角色前缀文字)。 【示例】NULL(用于本单结算操作员名称(带角色前缀文字))。 【JSON字段】settlement_ticket_details.json - $ - cashierName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '【说明】本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。 【示例】NULL(用于本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠))。 【JSON字段】settlement_ticket_details.json - $ - consumeMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '【说明】本单由优惠券抵扣的金额汇总。 【示例】NULL(用于本单由优惠券抵扣的金额汇总)。 【JSON字段】settlement_ticket_details.json - $ - couponAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '【说明】配送地址(若存在外送业务时使用)。 【示例】NULL(用于配送地址(若存在外送业务时使用))。 【JSON字段】settlement_ticket_details.json - $ - deliveryAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '【说明】配送费金额(如果支持外送业务)。 【示例】NULL(用于配送费金额(如果支持外送业务))。 【JSON字段】settlement_ticket_details.json - $ - deliveryFee。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '【说明】商品小计金额(通常 = 单价 × 数量,未考虑其他折扣)。 【示例】NULL(用于商品小计金额(通常 = 单价 × 数量,未考虑其他折扣))。 【JSON字段】settlement_ticket_details.json - $ - ledgerAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '【说明】会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。 【示例】NULL(用于会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用)。 【JSON字段】settlement_ticket_details.json - $ - memberDeductAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '【说明】由“会员权益/折扣”产生的优惠金额总计(整单维度)。 【示例】NULL(用于由“会员权益/折扣”产生的优惠金额总计(整单维度))。 【JSON字段】settlement_ticket_details.json - $ - memberOfferAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '【说明】本单通过线上支付渠道退回的金额(如微信/支付宝退款)。 【示例】NULL(用于本单通过线上支付渠道退回的金额(如微信/支付宝退款))。 【JSON字段】settlement_ticket_details.json - $ - onlineReturnAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '【说明】订单备注,由收银员录入,用于记录与本单相关的特殊说明。 【示例】NULL(订单备注,由收银员录入,用于记录与本单相关的特殊说明)。 【JSON字段】settlement_ticket_details.json - $ - orderRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '【说明】结算单编号(与 ID 独立的一套编号体系,如流水号)。 【示例】NULL(用于结算单编号(与 ID 独立的一套编号体系,如流水号))。 【JSON字段】settlement_ticket_details.json - $ - orderSettleNumber。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '【说明】使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。 【示例】NULL(使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用)。 【JSON字段】settlement_ticket_details.json - $ - payMemberBalance。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '【说明】本单最终支付成功时间。 【示例】NULL(用于本单最终支付成功时间)。 【JSON字段】settlement_ticket_details.json - $ - payTime。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '【说明】结算主支付方式编码(汇总视角)。 【示例】NULL(用于结算主支付方式编码(汇总视角))。 【JSON字段】settlement_ticket_details.json - $ - paymentMethod。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '【说明】积分抵扣对应的成本金额(成本侧)。 【示例】NULL(用于积分抵扣对应的成本金额(成本侧))。 【JSON字段】settlement_ticket_details.json - $ - pointDiscountCost。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '【说明】积分抵扣对应的金额(售价侧)。 【示例】NULL(用于积分抵扣对应的金额(售价侧))。 【JSON字段】settlement_ticket_details.json - $ - pointDiscountPrice。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '【说明】预付金/定金在本单中使用的金额。 【示例】NULL(用于预付金/定金在本单中使用的金额)。 【JSON字段】settlement_ticket_details.json - $ - prepayMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '【说明】本单涉及的退款金额(汇总)。 【示例】NULL(用于本单涉及的退款金额(汇总))。 【JSON字段】settlement_ticket_details.json - $ - refundAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '【说明】本单涉及的退货金额汇总。 【示例】NULL(用于本单涉及的退货金额汇总)。 【JSON字段】settlement_ticket_details.json - $ - returnGoodsAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '【说明】用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。 【示例】NULL(用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示)。 【JSON字段】settlement_ticket_details.json - $ - rewardName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '【说明】结算类型字符串标识。 【示例】NULL(用于结算类型字符串标识)。 【JSON字段】settlement_ticket_details.json - $ - settleType。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '【说明】门店地址(详细地址)。 【示例】NULL(用于门店地址(详细地址))。 【JSON字段】settlement_ticket_details.json - $ - siteAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '【说明】门店电话。 【示例】NULL(用于门店电话)。 【JSON字段】settlement_ticket_details.json - $ - siteBusinessTel。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】settlement_ticket_details.json - $ - siteId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '【说明】门店名称,如“朗朗桌球”。 【示例】NULL(用于门店名称,如“朗朗桌球”)。 【JSON字段】settlement_ticket_details.json - $ - siteName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '【说明】租户 / 商户 ID(品牌维度)。 【示例】NULL(用于租户 / 商户 ID(品牌维度))。 【JSON字段】settlement_ticket_details.json - $ - tenantId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '【说明】租户名称,如“朗朗桌球”。 【示例】NULL(用于租户名称,如“朗朗桌球”)。 【JSON字段】settlement_ticket_details.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '【说明】自定义小票内容,如商家自定义宣传语、条款等。 【示例】NULL(用于自定义小票内容,如商家自定义宣传语、条款等)。 【JSON字段】settlement_ticket_details.json - $ - ticketCustomContent。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '【说明】小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。 【示例】NULL(小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示))。 【JSON字段】settlement_ticket_details.json - $ - ticketRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '【说明】代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。 【示例】NULL(代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录))。 【JSON字段】settlement_ticket_details.json - $ - voucherMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '【说明】不是会员卡主键,而是本次结账时的会员信息快照。 【示例】NULL(用于不是会员卡主键,而是本次结账时的会员信息快照)。 【JSON字段】settlement_ticket_details.json - $ - memberProfile。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '【说明】本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。 【示例】NULL(用于本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构)。 【JSON字段】settlement_ticket_details.json - $ - orderItem。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlement_ticket_details.json - $ - tenantMemberCardLogs。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】settlement_ticket_details.json - $ - $。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_ticket_details.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_ticket_details.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】settlement_ticket_details.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ batch_stock_quantity NUMERIC(18,2),
+ days_available INT,
+ provisional_total_cost NUMERIC(18,2),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ sort INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS 'ODS 原始明细表:门店商品主数据。来源:export/test-json-doc/store_goods_master.json;分析:store_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '【说明】门店商品 ID,门店维度的商品主键。 【示例】2793025851560005(用于门店商品 ID,门店维度的商品主键)。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '【说明】门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。 【示例】朗朗桌球(用于门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案)。 【JSON字段】store_goods_master.json - data.orderGoodsList - siteName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '【说明】租户/品牌维度的商品 ID,相当于“全局商品 ID”。 【示例】2792178593255301(用于租户/品牌维度的商品 ID,相当于“全局商品 ID”)。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '【说明】商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。 【示例】合味道泡面(用于商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '【说明】商品条形码(如 EAN-13 编码),用于扫码销售。 【示例】NULL(商品条形码(如 EAN-13 编码),用于扫码销售)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2791941988405125(用于商品一级分类 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2793236829620037(用于商品二级分类 ID)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '【说明】一级分类名称,如“零食”“酒水”“服务费”等。 【示例】零食(用于一级分类名称,如“零食”“酒水”“服务费”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - oneCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '【说明】二级分类名称,如“面”“洋酒”“纸巾”等。 【示例】面(用于二级分类名称,如“面”“洋酒”“纸巾”等)。 【JSON字段】store_goods_master.json - data.orderGoodsList - twoCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '【说明】商品计量单位(销售单位)。 【示例】桶(用于商品计量单位(销售单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - unit。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '【说明】商品标准销售价(挂牌价),单位为元。 【示例】12.0(用于商品标准销售价(挂牌价),单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '【说明】商品成本价(单件成本)。 【示例】0.0(用于商品成本价(单件成本))。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '【说明】1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。 【示例】1(用于1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算)。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '【说明】最低允许成交价(限价)。 【示例】7.0(用于最低允许成交价(限价))。 【JSON字段】store_goods_master.json - data.orderGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '【说明】安全库存量(阈值),低于该值时系统可以提示补货。 【示例】0(用于安全库存量(阈值),低于该值时系统可以提示补货)。 【JSON字段】store_goods_master.json - data.orderGoodsList - safe_stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '【说明】当前可用库存数量(以 unit 为单位)。 【示例】18(用于当前可用库存数量(以 unit 为单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '【说明】副单位库存数量。 【示例】0(用于副单位库存数量)。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock_A。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '【说明】在当前统计口径下的销售数量(总销量,单位同 unit)。 【示例】104(用于在当前统计口径下的销售数量(总销量,单位同 unit))。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_num。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '【说明】总采购成本,单位为元。 【示例】0.0(用于总采购成本,单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '【说明】累计销售数量。 【示例】104(用于累计销售数量)。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '【说明】平均月销量(件/月),根据某个统计周期内的销售数据折算而来。 【示例】1.32(用于平均月销量(件/月),根据某个统计周期内的销售数据折算而来)。 【JSON字段】store_goods_master.json - data.orderGoodsList - average_monthly_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.batch_stock_quantity IS '【说明】当前“批次”的库存数量(主单位)。 【示例】43(用于当前“批次”的库存数量(主单位))。 【JSON字段】store_goods_master.json - data.orderGoodsList - batch_stock_quantity。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.days_available IS '【说明】商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间。 【示例】13(用于商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间)。 【JSON字段】store_goods_master.json - data.orderGoodsList - days_available。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.provisional_total_cost IS '【说明】暂估总成本,单位为元。 【示例】0.0(用于暂估总成本,单位为元)。 【JSON字段】store_goods_master.json - data.orderGoodsList - provisional_total_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '【说明】控制商品档案是否参与任何业务(库存、销售等)。 【示例】1(用于控制商品档案是否参与任何业务(库存、销售等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - enable_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '【说明】观察值:全部为 2。 【示例】2(用于观察值:全部为 2)。 【JSON字段】store_goods_master.json - data.orderGoodsList - audit_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '【说明】是否纳入库存管理。 【示例】1(用于是否纳入库存管理)。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '【说明】是否允许参与折扣。 【示例】1(用于是否允许参与折扣)。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '【说明】表示是否允许跨门店调拨或跨站点共享库存。 【示例】2(用于表示是否允许跨门店调拨或跨站点共享库存)。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】store_goods_master.json - data.orderGoodsList - forbid_sell_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】store_goods_master.json - data.orderGoodsList - send_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '【说明】自定义标签类型。 【示例】2(用于自定义标签类型)。 【JSON字段】store_goods_master.json - data.orderGoodsList - custom_label_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '【说明】是否需要在销售时选择规格/选项。 【示例】1(用于是否需要在销售时选择规格/选项)。 【JSON字段】store_goods_master.json - data.orderGoodsList - option_required。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '【说明】销售渠道类型。 【示例】1(用于销售渠道类型)。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sort IS '【说明】排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前)。 【示例】100(排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前))。 【JSON字段】store_goods_master.json - data.orderGoodsList - sort。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '【说明】商品备注(可以写口味说明、供应商、注意事项等)。 【示例】NULL(用于商品备注(可以写口味说明、供应商、注意事项等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '【说明】商品名称的拼音首字母缩写,有时多个别名用逗号分隔。 【示例】HWDPM,GWDPM(用于商品名称的拼音首字母缩写,有时多个别名用逗号分隔)。 【JSON字段】store_goods_master.json - data.orderGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '【说明】商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。 【示例】https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片)。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '【说明】门店商品档案创建时间(商品在门店建立档案的时间点)。 【示例】2025-07-16 11:52:51(用于门店商品档案创建时间(商品在门店建立档案的时间点))。 【JSON字段】store_goods_master.json - data.orderGoodsList - create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '【说明】最后一次修改该商品档案的时间(包括价格调整、状态变更等)。 【示例】2025-11-09 07:23:47(用于最后一次修改该商品档案的时间(包括价格调整、状态变更等))。 【JSON字段】store_goods_master.json - data.orderGoodsList - update_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】store_goods_master.json - data.orderGoodsList - $。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】store_goods_master.json - ETL元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ ordergoodsid BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ returns_number INT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS 'ODS 原始明细表:门店商品销售流水。来源:export/test-json-doc/store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '【说明】本条「门店销售流水」记录的主键 ID。 【示例】2957924029550406(用于本条「门店销售流水」记录的主键 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '【说明】门店 ID(系统主键)。 【示例】2790685415443269(用于门店 ID(系统主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - siteName。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '【说明】门店商品 ID。 【示例】2793026176012357(用于门店商品 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '【说明】租户(品牌)级商品 ID(全局商品 ID)。 【示例】2792115932417925(用于租户(品牌)级商品 ID(全局商品 ID))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '【说明】订单结算 ID(结账单主键)。 【示例】2957922914357125(用于订单结算 ID(结账单主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_settle_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '【说明】订单交易号(业务单号)。 【示例】2957858167230149(用于订单交易号(业务单号))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_trade_no。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '【说明】订单商品明细 ID(订单内部的商品行主键)。 【示例】2957858456391557(用于订单商品明细 ID(订单内部的商品行主键))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ordergoodsid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '【说明】关联支付记录的 ID。 【示例】0(用于关联支付记录的 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_pay_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '【说明】订单级优惠券 ID。 【示例】0(用于订单级优惠券 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '【说明】销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。 【示例】哇哈哈矿泉水(用于销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '【说明】销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。 【示例】酒水(用于销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '【说明】原始应收金额,公式上接近 ledger_unit_price × ledger_count。 【示例】5.0(用于原始应收金额,公式上接近 ledger_unit_price × ledger_count)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '【说明】销售数量(以 unit 为单位,unit 字段在门店商品档案中)。 【示例】1(用于销售数量(以 unit 为单位,unit 字段在门店商品档案中))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_count。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '【说明】商品在该次销售中的「结算单价」(元/单位)。 【示例】5.0(用于商品在该次销售中的「结算单价」(元/单位))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '【说明】销售流水状态。 【示例】1(用于销售流水状态)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '【说明】本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。 【示例】0.0(用于本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_price IS '【说明】折后单价(元/单位)。 【示例】5.0(用于折后单价(元/单位))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '【说明】被优惠券 / 团购券直接抵扣到这条商品明细上的金额。 【示例】0.0(用于被优惠券 / 团购券直接抵扣到这条商品明细上的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '【说明】由会员身份(会员折扣)针对这一行商品产生的优惠金额。 【示例】0.0(用于由会员身份(会员折扣)针对这一行商品产生的优惠金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '【说明】由优惠券抵扣“选项价格”的金额。 【示例】0.0(用于由优惠券抵扣“选项价格”的金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '【说明】由会员折扣作用在“选项价格”上的优惠金额。 【示例】0.0(用于由会员折扣作用在“选项价格”上的优惠金额)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_member_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '【说明】由积分抵扣的金额(顾客兑换积分抵现金额)。 【示例】0.0(用于由积分抵扣的金额(顾客兑换积分抵现金额))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '【说明】积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。 【示例】0.0(用于积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '【说明】商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。 【示例】5.0(用于商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - real_goods_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '【说明】本条销售对应的成本金额(以元计)。 【示例】0.01(用于本条销售对应的成本金额(以元计))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - cost_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '【说明】本条销售对应的提成金额(给营业员/促销员的提成)。 【示例】0.0(用于本条销售对应的提成金额(给营业员/促销员的提成))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - push_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '【说明】销售类型。 【示例】1(用于销售类型)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '【说明】是否单独订单标识。 【示例】1(用于是否单独订单标识)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_single_order。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '【说明】商品备注/口味说明/特殊说明。 【示例】哇哈哈矿泉水(用于商品备注/口味说明/特殊说明)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - goods_remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '【说明】商品选项(规格/加料)的附加价格。 【示例】0.0(用于商品选项(规格/加料)的附加价格)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '【说明】商品选项名称(如规格、口味:大杯/小杯,不加冰等)。 【示例】NULL(用于商品选项名称(如规格、口味:大杯/小杯,不加冰等))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_value_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '【说明】会员券 ID(比如会员专享优惠券)。 【示例】0(用于会员券 ID(比如会员专享优惠券))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '【说明】套餐券 ID。 【示例】0(用于套餐券 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - package_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '【说明】营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。 【示例】NULL(用于营业员姓名(如果有为具体销售员记业绩,则在此填姓名))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '【说明】营业员的系统角色 ID(例如某个角色代码表示“销售员”)。 【示例】0(用于营业员的系统角色 ID(例如某个角色代码表示“销售员”))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '【说明】营业员用户 ID(系统账号 ID)。 【示例】0(用于营业员用户 ID(系统账号 ID))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '【说明】操作员 ID(录入这笔销售的员工)。 【示例】2790687322443013(用于操作员 ID(录入这笔销售的员工))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '【说明】操作员姓名,文字冗余。 【示例】收银员:郑丽珊(用于操作员姓名,文字冗余)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - openSalesman。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.returns_number IS '【说明】退货数量(如果这条明细做了退货,会记录退货数量)。 【示例】0(用于退货数量(如果这条明细做了退货,会记录退货数量))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - returns_number。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_table_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '【说明】租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。 【示例】2790683528317768(用于租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度))。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '【说明】租户级商品一级分类 ID。 【示例】2790683528350540(用于租户级商品一级分类 ID)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '【说明】销售记录创建时间,通常就是结账时间或录入时间。 【示例】2025-11-09 23:35:57(用于销售记录创建时间,通常就是结账时间或录入时间)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - $。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_sales_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_sales_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】store_goods_sales_records.json - ETL元数据 - 无。';
+
+
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/schema_dwd_doc.sql b/etl_billiards/dist/ETL_Manager/_internal/database/schema_dwd_doc.sql
new file mode 100644
index 0000000..15bf56c
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/schema_dwd_doc.sql
@@ -0,0 +1,2016 @@
+CREATE SCHEMA IF NOT EXISTS billiards_dwd;
+SET search_path TO billiards_dwd;
+
+CREATE EXTENSION IF NOT EXISTS btree_gist;
+
+DO $$
+DECLARE
+ rec RECORD;
+BEGIN
+ FOR rec IN
+ SELECT table_name
+ FROM information_schema.columns
+ WHERE table_schema = 'billiards_dwd'
+ AND column_name = 'scd2_start_time'
+ LOOP
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_start_time SET DEFAULT now()', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_end_time SET DEFAULT ''9999-12-31''', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_is_current SET DEFAULT 1', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_version SET DEFAULT 1', rec.table_name);
+
+ END LOOP;
+
+ FOR rec IN (
+ SELECT tc.table_name,
+ string_agg(format('%I WITH =', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_eq_expr,
+ string_agg(format('%I', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_cols
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.table_schema = kcu.table_schema
+ AND tc.table_name = kcu.table_name
+ AND tc.constraint_name = kcu.constraint_name
+ WHERE tc.table_schema = 'billiards_dwd'
+ AND tc.constraint_type = 'PRIMARY KEY'
+ AND EXISTS (
+ SELECT 1 FROM information_schema.columns c
+ WHERE c.table_schema = 'billiards_dwd'
+ AND c.table_name = tc.table_name
+ AND c.column_name = 'scd2_start_time'
+ )
+ GROUP BY tc.table_name
+ )
+ LOOP
+ IF NOT EXISTS (
+ SELECT 1 FROM pg_constraint
+ WHERE conname = format('%s_scd2_no_overlap', rec.table_name)
+ AND conrelid = format('billiards_dwd.%s', rec.table_name)::regclass
+ ) THEN
+ EXECUTE format(
+ 'ALTER TABLE billiards_dwd.%I ADD CONSTRAINT %I EXCLUDE USING gist (%s, tstzrange(scd2_start_time, scd2_end_time) WITH &&) WHERE (scd2_is_current = 1);',
+ rec.table_name,
+ rec.table_name || '_scd2_no_overlap',
+ rec.pk_eq_expr
+ );
+ END IF;
+
+ IF to_regclass(format('billiards_dwd.%s_scd2_current_unique_idx', rec.table_name)) IS NULL THEN
+ EXECUTE format(
+ 'CREATE UNIQUE INDEX %I ON billiards_dwd.%I (%s) WHERE (scd2_is_current = 1);',
+ rec.table_name || '_scd2_current_unique_idx',
+ rec.table_name,
+ rec.pk_cols
+ );
+ END IF;
+ END LOOP;
+END
+$$;
+
+
+CREATE TABLE IF NOT EXISTS dim_site (
+ site_id BIGINT,
+ org_id BIGINT,
+ tenant_id BIGINT,
+ shop_name TEXT,
+ site_label TEXT,
+ full_address TEXT,
+ address TEXT,
+ longitude NUMERIC(10,6),
+ latitude NUMERIC(10,6),
+ tenant_site_region_id BIGINT,
+ business_tel TEXT,
+ site_type INTEGER,
+ shop_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_site IS 'DWD 维度表:dim_site。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.org_id IS '【说明】组织/机构 ID,用于组织维度归属。 【示例】2790684179467077(组织/机构 ID,用于组织维度归属)。 【ODS来源】table_fee_transactions - siteProfile.org_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - org_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.tenant_id IS '【说明】租户/品牌 ID,用于商户维度过滤与关联。 【示例】2790683160709957(租户/品牌 ID,用于商户维度过滤与关联)。 【ODS来源】table_fee_transactions - siteProfile.tenant_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.shop_name IS '【说明】门店名称,用于展示与查询。 【示例】朗朗桌球(门店名称,用于展示与查询)。 【ODS来源】table_fee_transactions - siteProfile.shop_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_name。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_label IS '【说明】门店标签(如 A/B 店),用于展示与分组。 【示例】A(门店标签(如 A/B 店),用于展示与分组)。 【ODS来源】table_fee_transactions - siteProfile.site_label。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_label。';
+COMMENT ON COLUMN billiards_dwd.dim_site.full_address IS '【说明】门店详细地址,用于展示与地理信息。 【示例】广东省广州市天河区丽阳街12号(门店详细地址,用于展示与地理信息)。 【ODS来源】table_fee_transactions - siteProfile.full_address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - full_address。';
+COMMENT ON COLUMN billiards_dwd.dim_site.address IS '【说明】门店地址简称/快照,用于展示。 【示例】广东省广州市天河区天园街道朗朗桌球(门店地址简称/快照,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - address。';
+COMMENT ON COLUMN billiards_dwd.dim_site.longitude IS '【说明】经度,用于定位与地图展示。 【示例】113.360321(经度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.longitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - longitude(派生:CAST(longitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site.latitude IS '【说明】纬度,用于定位与地图展示。 【示例】23.133629(纬度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.latitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - latitude(派生:CAST(latitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site.tenant_site_region_id IS '【说明】租户下门店区域 ID,用于区域维度分析。 【示例】156440100(租户下门店区域 ID,用于区域维度分析)。 【ODS来源】table_fee_transactions - siteProfile.tenant_site_region_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_site_region_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site.business_tel IS '【说明】门店电话,用于联系信息展示。 【示例】13316068642(门店电话,用于联系信息展示)。 【ODS来源】table_fee_transactions - siteProfile.business_tel。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - business_tel。';
+COMMENT ON COLUMN billiards_dwd.dim_site.site_type IS '【说明】门店类型枚举,用于门店分类。 【示例】1(门店类型枚举,用于门店分类)。 【ODS来源】table_fee_transactions - siteProfile.site_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site.shop_status IS '【说明】门店状态枚举,用于营业状态标识。 【示例】1(门店状态枚举,用于营业状态标识)。 【ODS来源】table_fee_transactions - siteProfile.shop_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_site_Ex (
+ site_id BIGINT,
+ avatar TEXT,
+ address TEXT,
+ longitude NUMERIC(9,6),
+ latitude NUMERIC(9,6),
+ tenant_site_region_id BIGINT,
+ auto_light INTEGER,
+ light_status INTEGER,
+ light_type INTEGER,
+ light_token TEXT,
+ site_type INTEGER,
+ site_label TEXT,
+ attendance_enabled INTEGER,
+ attendance_distance INTEGER,
+ customer_service_qrcode TEXT,
+ customer_service_wechat TEXT,
+ fixed_pay_qrCode TEXT,
+ prod_env TEXT,
+ shop_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_site_ex IS 'DWD 维度表(扩展字段表):dim_site_ex。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.avatar IS '【说明】门店头像/图片 URL,用于展示。 【示例】https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg(门店头像/图片 URL,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.avatar。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - avatar。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.address IS '【说明】门店地址简称/快照,用于展示。 【示例】广东省广州市天河区天园街道朗朗桌球(门店地址简称/快照,用于展示)。 【ODS来源】table_fee_transactions - siteProfile.address。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - address。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.longitude IS '【说明】经度,用于定位与地图展示。 【示例】113.360321(经度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.longitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - longitude(派生:CAST(longitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.latitude IS '【说明】纬度,用于定位与地图展示。 【示例】23.133629(纬度,用于定位与地图展示)。 【ODS来源】table_fee_transactions - siteProfile.latitude。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - latitude(派生:CAST(latitude AS numeric))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.tenant_site_region_id IS '【说明】租户下门店区域 ID,用于区域维度分析。 【示例】156440100(租户下门店区域 ID,用于区域维度分析)。 【ODS来源】table_fee_transactions - siteProfile.tenant_site_region_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_site_region_id。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.auto_light IS '【说明】是否启用自动灯控配置,用于门店设备策略。 【示例】1(是否启用自动灯控配置,用于门店设备策略)。 【ODS来源】table_fee_transactions - siteProfile.auto_light。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - auto_light。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_status IS '【说明】灯控状态/开关,用于灯控设备管理。 【示例】1(灯控状态/开关,用于灯控设备管理)。 【ODS来源】table_fee_transactions - siteProfile.light_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_type IS '【说明】灯控类型,用于设备类型区分。 【示例】0(灯控类型,用于设备类型区分)。 【ODS来源】table_fee_transactions - siteProfile.light_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.light_token IS '【说明】灯控控制令牌,用于对接灯控服务。 【示例】NULL(灯控控制令牌,用于对接灯控服务)。 【ODS来源】table_fee_transactions - siteProfile.light_token。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - light_token。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_type IS '【说明】门店类型枚举,用于门店分类。 【示例】1(门店类型枚举,用于门店分类)。 【ODS来源】table_fee_transactions - siteProfile.site_type。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_type。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.site_label IS '【说明】门店标签(如 A/B 店),用于展示与分组。 【示例】A(门店标签(如 A/B 店),用于展示与分组)。 【ODS来源】table_fee_transactions - siteProfile.site_label。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_label。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.attendance_enabled IS '【说明】是否启用考勤功能,用于门店考勤配置。 【示例】1(是否启用考勤功能,用于门店考勤配置)。 【ODS来源】table_fee_transactions - siteProfile.attendance_enabled。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - attendance_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.attendance_distance IS '【说明】考勤允许距离(米),用于考勤打卡限制。 【示例】0(考勤允许距离(米),用于考勤打卡限制)。 【ODS来源】table_fee_transactions - siteProfile.attendance_distance。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - attendance_distance。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.customer_service_qrcode IS '【说明】客服二维码 URL,用于引导联系。 【示例】NULL(客服二维码 URL,用于引导联系)。 【ODS来源】table_fee_transactions - siteProfile.customer_service_qrcode。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - customer_service_qrcode。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.customer_service_wechat IS '【说明】客服微信号,用于引导联系。 【示例】NULL(客服微信号,用于引导联系)。 【ODS来源】table_fee_transactions - siteProfile.customer_service_wechat。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - customer_service_wechat。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.fixed_pay_qrcode IS '【说明】固定收款码(二维码)URL,用于收款引导。 【示例】NULL(固定收款码(二维码)URL,用于收款引导)。 【ODS来源】table_fee_transactions - siteProfile.fixed_pay_qrCode。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - fixed_pay_qrCode。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.prod_env IS '【说明】环境标识(生产/测试),用于区分配置环境。 【示例】1(环境标识(生产/测试),用于区分配置环境)。 【ODS来源】table_fee_transactions - siteProfile.prod_env。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - prod_env。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.shop_status IS '【说明】门店状态枚举,用于营业状态标识。 【示例】1(门店状态枚举,用于营业状态标识)。 【ODS来源】table_fee_transactions - siteProfile.shop_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_status。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.create_time IS '【说明】门店创建时间(快照字段)。 【示例】NULL(用于门店创建时间(快照字段))。 【ODS来源】table_fee_transactions - siteProfile.create_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - create_time(派生:CAST(create_time AS timestamptz))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.update_time IS '【说明】门店更新时间(快照字段)。 【示例】NULL(用于门店更新时间(快照字段))。 【ODS来源】table_fee_transactions - siteProfile.update_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - update_time(派生:CAST(update_time AS timestamptz))。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_site_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】table_fee_transactions - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_table (
+ table_id BIGINT,
+ site_id BIGINT,
+ table_name TEXT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ table_price NUMERIC(18,2),
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_table IS 'DWD 维度表:dim_table。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791964216463493(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - id。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_id。 【JSON字段】site_tables_master.json - data.siteTables - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A1(名称字段,用于展示与辅助识别)。 【ODS来源】site_tables_master - table_name。 【JSON字段】site_tables_master.json - data.siteTables - table_name。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_table_area_id。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.site_table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】site_tables_master - areaName。 【JSON字段】site_tables_master.json - data.siteTables - areaName。';
+COMMENT ON COLUMN billiards_dwd.dim_table.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - site_table_area_id。 【JSON字段】site_tables_master.json - data.siteTables - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_table.table_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】site_tables_master - table_price。 【JSON字段】site_tables_master.json - data.siteTables - table_price。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_table_Ex (
+ table_id BIGINT,
+ show_status INTEGER,
+ is_online_reservation INTEGER,
+ table_cloth_use_time INTEGER,
+ table_cloth_use_cycle INTEGER,
+ table_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_table_ex IS 'DWD 维度表(扩展字段表):dim_table_ex。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791964216463493(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】site_tables_master - id。 【JSON字段】site_tables_master.json - data.siteTables - id。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.show_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】site_tables_master - show_status。 【JSON字段】site_tables_master.json - data.siteTables - show_status。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.is_online_reservation IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】2(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】site_tables_master - is_online_reservation。 【JSON字段】site_tables_master.json - data.siteTables - is_online_reservation。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_cloth_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】1863727(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】site_tables_master - table_cloth_use_time。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_time。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_cloth_use_cycle IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】site_tables_master - table_cloth_use_Cycle。 【JSON字段】site_tables_master.json - data.siteTables - table_cloth_use_Cycle。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.table_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】site_tables_master - table_status。 【JSON字段】site_tables_master.json - data.siteTables - table_status。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_table_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】site_tables_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_assistant (
+ assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_no TEXT,
+ real_name TEXT,
+ nickname TEXT,
+ mobile TEXT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ team_id BIGINT,
+ team_name TEXT,
+ level INTEGER,
+ entry_time TIMESTAMPTZ,
+ resign_time TIMESTAMPTZ,
+ leave_status INTEGER,
+ assistant_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_assistant IS 'DWD 维度表:dim_assistant。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271297029(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_no IS '【说明】维度字段,用于补充维度属性。 【示例】31(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - assistant_no。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_no。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.real_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】张静然(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - real_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - real_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】小然(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - nickname。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - nickname。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.mobile IS '【说明】维度字段,用于补充维度属性。 【示例】15119679931(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - mobile。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - tenant_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - site_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.team_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792011585884037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - team_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.team_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】1组(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - team_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - team_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.level IS '【说明】维度字段,用于补充维度属性。 【示例】20(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - level。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - level。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.entry_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-02 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - entry_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.resign_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-03 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - resign_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.leave_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - leave_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - leave_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.assistant_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - assistant_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
+ assistant_id BIGINT,
+ gender INTEGER,
+ birth_date TIMESTAMPTZ,
+ avatar TEXT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ height NUMERIC(5,2),
+ weight NUMERIC(5,2),
+ shop_name TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ person_org_id BIGINT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ assistant_grade DOUBLE PRECISION,
+ sum_grade DOUBLE PRECISION,
+ get_grade_times INTEGER,
+ charge_way INTEGER,
+ allow_cx INTEGER,
+ is_guaranteed INTEGER,
+ salary_grant_enabled INTEGER,
+ entry_type INTEGER,
+ entry_sign_status INTEGER,
+ resign_sign_status INTEGER,
+ work_status INTEGER,
+ show_status INTEGER,
+ show_sort INTEGER,
+ online_status INTEGER,
+ is_delete INTEGER,
+ criticism_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ last_update_name TEXT,
+ order_trade_no BIGINT,
+ ding_talk_synced INTEGER,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ light_status INTEGER,
+ is_team_leader INTEGER,
+ serial_number BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_assistant_ex IS 'DWD 维度表(扩展字段表):dim_assistant_ex。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271297029(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.gender IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - gender。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - gender。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.birth_date IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - birth_date。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - birth_date。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.avatar IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - avatar。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - avatar。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.introduce IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - introduce。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - introduce。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.video_introduction_url IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/cbb/userVideo/1753096246308/175309624630830.mp4(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - video_introduction_url。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - video_introduction_url。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.height IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - height。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - height。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.weight IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - weight。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - weight。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.shop_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - shop_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - shop_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.group_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - group_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - group_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - group_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.person_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2947562271215109(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - person_org_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - person_org_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.staff_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.staff_profile_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - staff_profile_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - staff_profile_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.assistant_grade IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - assistant_grade。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - assistant_grade。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.sum_grade IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - sum_grade。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - sum_grade。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.get_grade_times IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - get_grade_times。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - get_grade_times。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.charge_way IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - charge_way。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - charge_way。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.allow_cx IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - allow_cx。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - allow_cx。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_guaranteed IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_guaranteed。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_guaranteed。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.salary_grant_enabled IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - salary_grant_enabled。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - salary_grant_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.entry_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - entry_type。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_type。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.entry_sign_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - entry_sign_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - entry_sign_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.resign_sign_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - resign_sign_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - resign_sign_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.work_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - work_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - work_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.show_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - show_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.show_sort IS '【说明】维度字段,用于补充维度属性。 【示例】31(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - show_sort。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - show_sort。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.online_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - online_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - online_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_delete。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.criticism_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - criticism_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - criticism_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-02 15:55:26(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - create_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-03 18:32:07(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - update_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-01 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - start_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-12-01 08:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_accounts_master - end_time。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - last_table_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】TV(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - last_table_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_table_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.last_update_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】管理员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_accounts_master - last_update_name。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - last_update_name。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.order_trade_no IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - order_trade_no。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.ding_talk_synced IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】assistant_accounts_master - ding_talk_synced。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - ding_talk_synced。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.site_light_cfg_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - site_light_cfg_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - site_light_cfg_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.light_equipment_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_accounts_master - light_equipment_id。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_equipment_id。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.light_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_accounts_master - light_status。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - light_status。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.is_team_leader IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_accounts_master - is_team_leader。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - is_team_leader。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_accounts_master - serial_number。 【JSON字段】assistant_accounts_master.json - data.assistantInfos - serial_number。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_assistant_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】assistant_accounts_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_member (
+ member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ mobile TEXT,
+ nickname TEXT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_member IS 'DWD 维度表:dim_member。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204540009605(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - system_member_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - tenant_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - register_site_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member.mobile IS '【说明】维度字段,用于补充维度属性。 【示例】18620043391(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - mobile。 【JSON字段】member_profiles.json - data.tenantMemberInfos - mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_member.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】胡先生(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - nickname。 【JSON字段】member_profiles.json - data.tenantMemberInfos - nickname。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_card_grade_code IS '【说明】维度字段,用于补充维度属性。 【示例】2790683528022853(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - member_card_grade_code。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_code。';
+COMMENT ON COLUMN billiards_dwd.dim_member.member_card_grade_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】储值卡(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - member_card_grade_name。 【JSON字段】member_profiles.json - data.tenantMemberInfos - member_card_grade_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:29:33(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_profiles - create_time。 【JSON字段】member_profiles.json - data.tenantMemberInfos - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_profiles - update_time。 【JSON字段】member_profiles.json - data.tenantMemberInfos - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_member_Ex (
+ member_id BIGINT,
+ referrer_member_id BIGINT,
+ point NUMERIC(18,2),
+ register_site_name TEXT,
+ growth_value NUMERIC(18,2),
+ user_status INTEGER,
+ status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_member_ex IS 'DWD 维度表(扩展字段表):dim_member_ex。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.referrer_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_profiles - referrer_member_id。 【JSON字段】member_profiles.json - data.tenantMemberInfos - referrer_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.point IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - point。 【JSON字段】member_profiles.json - data.tenantMemberInfos - point。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.register_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_profiles - site_name。 【JSON字段】member_profiles.json - data.tenantMemberInfos - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.growth_value IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_profiles - growth_value。 【JSON字段】member_profiles.json - data.tenantMemberInfos - growth_value。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.user_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_profiles - user_status。 【JSON字段】member_profiles.json - data.tenantMemberInfos - user_status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_profiles - status。 【JSON字段】member_profiles.json - data.tenantMemberInfos - status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_profiles - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_member_card_account (
+ member_card_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ card_type_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ balance NUMERIC(18,2),
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_consume_time TIMESTAMPTZ,
+ status INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_member_card_account IS 'DWD 维度表:dim_member_card_account。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955206162843781(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - tenant_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - register_site_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204541320325(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - tenant_member_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955204540009605(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - system_member_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.card_type_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793266846533445(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - card_type_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_type_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_grade_code IS '【说明】维度字段,用于补充维度属性。 【示例】2790683528022856(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - member_card_grade_code。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_grade_code_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】活动抵用券(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_card_grade_code_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】活动抵用券(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_card_type_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_card_type_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】胡先生(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - member_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.member_mobile IS '【说明】维度字段,用于补充维度属性。 【示例】18620043391(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - member_mobile。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - member_mobile。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.balance IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - balance。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - balance。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:31:12(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - start_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2225-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - end_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.last_consume_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 07:48:23(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - last_consume_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - last_consume_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】member_stored_value_cards - status。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - status。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_stored_value_cards - is_delete。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
+ member_card_id BIGINT,
+ site_name TEXT,
+ tenant_name VARCHAR(64),
+ tenantAvatar TEXT,
+ effect_site_id BIGINT,
+ able_cross_site INTEGER,
+ card_physics_type INTEGER,
+ card_no TEXT,
+ bind_password TEXT,
+ use_scene TEXT,
+ denomination NUMERIC(18,2),
+ create_time TIMESTAMPTZ,
+ disable_start_time TIMESTAMPTZ,
+ disable_end_time TIMESTAMPTZ,
+ is_allow_give INTEGER,
+ is_allow_order_deduct INTEGER,
+ sort INTEGER,
+ table_discount NUMERIC(10,2),
+ goods_discount NUMERIC(10,2),
+ assistant_discount NUMERIC(10,2),
+ assistant_reward_discount NUMERIC(10,2),
+ table_service_discount NUMERIC(10,2),
+ goods_service_discount NUMERIC(10,2),
+ assistant_service_discount NUMERIC(10,2),
+ coupon_discount NUMERIC(10,2),
+ table_discount_sub_switch INTEGER,
+ goods_discount_sub_switch INTEGER,
+ assistant_discount_sub_switch INTEGER,
+ assistant_reward_discount_sub_switch INTEGER,
+ goods_discount_range_type INTEGER,
+ table_deduct_radio NUMERIC(10,2),
+ goods_deduct_radio NUMERIC(10,2),
+ assistant_deduct_radio NUMERIC(10,2),
+ table_service_deduct_radio NUMERIC(10,2),
+ goods_service_deduct_radio NUMERIC(10,2),
+ assistant_service_deduct_radio NUMERIC(10,2),
+ assistant_reward_deduct_radio NUMERIC(10,2),
+ coupon_deduct_radio NUMERIC(10,2),
+ cardSettleDeduct NUMERIC(18,2),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ tableAreaId TEXT,
+ goodsCategoryId TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_member_card_account_ex IS 'DWD 维度表(扩展字段表):dim_member_card_account_ex。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955206162843781(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - site_name。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tenant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】member_stored_value_cards - tenantName。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantName。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tenantavatar IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - tenantAvatar。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tenantAvatar。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.effect_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_stored_value_cards - effect_site_id。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - effect_site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.able_cross_site IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - able_cross_site。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - able_cross_site。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.card_physics_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - card_physics_type。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_physics_type。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.card_no IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - card_no。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - card_no。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.bind_password IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - bind_password。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - bind_password。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.use_scene IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - use_scene。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - use_scene。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.denomination IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - denomination。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - denomination。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:31:12(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - create_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.disable_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - disable_start_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.disable_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_stored_value_cards - disable_end_time。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - disable_end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.is_allow_give IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_stored_value_cards - is_allow_give。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_give。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.is_allow_order_deduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - is_allow_order_deduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - is_allow_order_deduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.sort IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - sort。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_reward_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_service_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - coupon_discount。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - table_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - assistant_reward_discount_sub_switch。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_discount_sub_switch。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_discount_range_type IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】member_stored_value_cards - goods_discount_range_type。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_discount_range_type。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - table_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goods_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.table_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - table_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - table_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goods_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goods_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goods_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_service_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_service_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_service_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistant_reward_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistant_reward_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistant_reward_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.coupon_deduct_radio IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】100.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - coupon_deduct_radio。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - coupon_deduct_radio。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.cardsettlededuct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - cardSettleDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cardSettleDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tablecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - tableCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tableservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - tableServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodscardeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goodsCarDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCarDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodsservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - goodsServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantservicecarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantServiceCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantServiceCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.assistantrewardcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - assistantRewardCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - assistantRewardCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.couponcarddeduct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - couponCardDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - couponCardDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.deliveryfeededuct IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_stored_value_cards - deliveryFeeDeduct。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - deliveryFeeDeduct。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.tableareaid IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - tableAreaId。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - tableAreaId。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.goodscategoryid IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - goodsCategoryId。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - goodsCategoryId。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.pdassisnatlevel IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - pdAssisnatLevel。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - pdAssisnatLevel。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.cxassisnatlevel IS '【说明】维度字段,用于补充维度属性。 【示例】[](维度字段,用于补充维度属性)。 【ODS来源】member_stored_value_cards - cxAssisnatLevel。 【JSON字段】member_stored_value_cards.json - data.tenantMemberCards - cxAssisnatLevel。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_member_card_account_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】member_stored_value_cards - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_tenant_goods (
+ tenant_goods_id BIGINT,
+ tenant_id BIGINT,
+ supplier_id BIGINT,
+ category_name VARCHAR(64),
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ goods_name VARCHAR(128),
+ goods_number VARCHAR(64),
+ unit VARCHAR(16),
+ market_price NUMERIC(18,2),
+ goods_state INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_tenant_goods IS 'DWD 维度表:dim_tenant_goods。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791925230096261(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - tenant_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.supplier_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - supplier_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - supplier_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.category_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】饮料(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - categoryName。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - categoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350539(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - goods_category_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_second_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350540(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - goods_second_category_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】东方树叶(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - goods_name。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】tenant_goods_master - goods_number。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_number。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.unit IS '【说明】维度字段,用于补充维度属性。 【示例】瓶(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - unit。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - unit。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.market_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】8.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - market_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - market_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.goods_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_state。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-07-15 17:13:15(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】tenant_goods_master - create_time。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.update_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-29 23:51:38(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】tenant_goods_master - update_time。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - is_delete。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
+ tenant_goods_id BIGINT,
+ remark_name VARCHAR(128),
+ pinyin_initial VARCHAR(128),
+ goods_cover VARCHAR(512),
+ goods_bar_code VARCHAR(64),
+ commodity_code VARCHAR(64),
+ commodity_code_list VARCHAR(256),
+ min_discount_price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ cost_price_type INTEGER,
+ able_discount INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ is_in_site BOOLEAN,
+ able_site_transfer INTEGER,
+ common_sale_royalty INTEGER,
+ point_sale_royalty INTEGER,
+ out_goods_id BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_tenant_goods_ex IS 'DWD 维度表(扩展字段表):dim_tenant_goods_ex。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791925230096261(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.remark_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】tenant_goods_master - remark_name。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - remark_name。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.pinyin_initial IS '【说明】维度字段,用于补充维度属性。 【示例】DFSY,DFSX(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - pinyin_initial。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.goods_cover IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_cover。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.goods_bar_code IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - goods_bar_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.commodity_code IS '【说明】维度字段,用于补充维度属性。 【示例】10000028(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - commodity_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.commodity_code_list IS '【说明】维度字段,用于补充维度属性。 【示例】10000028(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - commodity_code。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - commodity_code。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.min_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - min_discount_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.cost_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - cost_price。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.cost_price_type IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】1(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】tenant_goods_master - cost_price_type。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.able_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】tenant_goods_master - able_discount。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.sale_channel IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - sale_channel。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - is_warehousing。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.is_in_site IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】false(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】tenant_goods_master - isInSite(派生:BOOLEAN(isInSite))。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - isInSite(派生:BOOLEAN(isInSite))。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.able_site_transfer IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - able_site_transfer。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.common_sale_royalty IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - common_sale_royalty。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - common_sale_royalty。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.point_sale_royalty IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】tenant_goods_master - point_sale_royalty。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - point_sale_royalty。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.out_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】tenant_goods_master - out_goods_id。 【JSON字段】tenant_goods_master.json - data.tenantGoodsList - out_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_tenant_goods_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】tenant_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_store_goods (
+ site_goods_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ category_level1_name TEXT,
+ category_level2_name TEXT,
+ batch_stock_qty INTEGER,
+ sale_qty INTEGER,
+ total_sales_qty INTEGER,
+ sale_price NUMERIC(18,2),
+ created_at TIMESTAMPTZ,
+ updated_at TIMESTAMPTZ,
+ avg_monthly_sales NUMERIC(18,4),
+ goods_state INTEGER,
+ enable_status INTEGER,
+ send_state INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_store_goods IS 'DWD 维度表:dim_store_goods。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793025851560005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - id。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - tenant_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - site_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792178593255301(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - tenant_goods_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - tenant_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】合味道泡面(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - goods_name。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_name。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791941988405125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - goods_category_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_second_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793236829620037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - goods_second_category_id。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_second_category_id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.category_level1_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】零食(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - oneCategoryName。 【JSON字段】store_goods_master.json - data.orderGoodsList - oneCategoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.category_level2_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】面(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - twoCategoryName。 【JSON字段】store_goods_master.json - data.orderGoodsList - twoCategoryName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.batch_stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】18(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.sale_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】104(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - sale_num。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_num。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.total_sales_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】104(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - total_sales。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_sales。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.sale_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】12.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - sale_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.created_at IS '【说明】维度字段,用于补充维度属性。 【示例】2025-07-16 11:52:51(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - create_time。 【JSON字段】store_goods_master.json - data.orderGoodsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.updated_at IS '【说明】维度字段,用于补充维度属性。 【示例】2025-11-09 07:23:47(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - update_time。 【JSON字段】store_goods_master.json - data.orderGoodsList - update_time。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.avg_monthly_sales IS '【说明】维度字段,用于补充维度属性。 【示例】1.32(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - average_monthly_sales。 【JSON字段】store_goods_master.json - data.orderGoodsList - average_monthly_sales。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.goods_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_state。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_state。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.enable_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - enable_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - enable_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.send_state IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - send_state。 【JSON字段】store_goods_master.json - data.orderGoodsList - send_state。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_master - is_delete。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
+ site_goods_id BIGINT,
+ site_name TEXT,
+ unit TEXT,
+ goods_barcode TEXT,
+ goods_cover_url TEXT,
+ pinyin_initial TEXT,
+ stock_qty INTEGER,
+ stock_secondary_qty INTEGER,
+ safety_stock_qty INTEGER,
+ cost_price NUMERIC(18,4),
+ cost_price_type INTEGER,
+ provisional_total_cost NUMERIC(18,2),
+ total_purchase_cost NUMERIC(18,2),
+ min_discount_price NUMERIC(18,2),
+ is_discountable INTEGER,
+ days_on_shelf INTEGER,
+ audit_status INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ freeze_status INTEGER,
+ forbid_sell_status INTEGER,
+ able_site_transfer INTEGER,
+ custom_label_type INTEGER,
+ option_required INTEGER,
+ remark TEXT,
+ sort_order INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_store_goods_ex IS 'DWD 维度表(扩展字段表):dim_store_goods_ex。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793025851560005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_master - id。 【JSON字段】store_goods_master.json - data.orderGoodsList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_master - siteName。 【JSON字段】store_goods_master.json - data.orderGoodsList - siteName。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.unit IS '【说明】维度字段,用于补充维度属性。 【示例】桶(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - unit。 【JSON字段】store_goods_master.json - data.orderGoodsList - unit。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.goods_barcode IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_bar_code。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_bar_code。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.goods_cover_url IS '【说明】维度字段,用于补充维度属性。 【示例】https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - goods_cover。 【JSON字段】store_goods_master.json - data.orderGoodsList - goods_cover。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.pinyin_initial IS '【说明】维度字段,用于补充维度属性。 【示例】HWDPM,GWDPM(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - pinyin_initial。 【JSON字段】store_goods_master.json - data.orderGoodsList - pinyin_initial。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】18(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.stock_secondary_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - stock_A。 【JSON字段】store_goods_master.json - data.orderGoodsList - stock_A。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.safety_stock_qty IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - safe_stock。 【JSON字段】store_goods_master.json - data.orderGoodsList - safe_stock。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.cost_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - cost_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.cost_price_type IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】1(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - cost_price_type。 【JSON字段】store_goods_master.json - data.orderGoodsList - cost_price_type。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.provisional_total_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - total_purchase_cost。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.total_purchase_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - total_purchase_cost。 【JSON字段】store_goods_master.json - data.orderGoodsList - total_purchase_cost。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.min_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】7.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_master - min_discount_price。 【JSON字段】store_goods_master.json - data.orderGoodsList - min_discount_price。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.is_discountable IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_master - able_discount。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_discount。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.days_on_shelf IS '【说明】维度字段,用于补充维度属性。 【示例】13(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - days_available。 【JSON字段】store_goods_master.json - data.orderGoodsList - days_available。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.audit_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - audit_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - audit_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.sale_channel IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - sale_channel。 【JSON字段】store_goods_master.json - data.orderGoodsList - sale_channel。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_master - is_warehousing。 【JSON字段】store_goods_master.json - data.orderGoodsList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.freeze_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】0(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - freeze。 【JSON字段】store_goods_master.json - data.orderGoodsList - freeze。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.forbid_sell_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_master - forbid_sell_status。 【JSON字段】store_goods_master.json - data.orderGoodsList - forbid_sell_status。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.able_site_transfer IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - able_site_transfer。 【JSON字段】store_goods_master.json - data.orderGoodsList - able_site_transfer。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.custom_label_type IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - custom_label_type。 【JSON字段】store_goods_master.json - data.orderGoodsList - custom_label_type。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.option_required IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - option_required。 【JSON字段】store_goods_master.json - data.orderGoodsList - option_required。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.remark IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - remark。 【JSON字段】store_goods_master.json - data.orderGoodsList - remark。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.sort_order IS '【说明】维度字段,用于补充维度属性。 【示例】100(维度字段,用于补充维度属性)。 【ODS来源】store_goods_master - sort。 【JSON字段】store_goods_master.json - data.orderGoodsList - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_store_goods_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】store_goods_master - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_goods_category (
+ category_id BIGINT,
+ tenant_id BIGINT,
+ category_name VARCHAR(50),
+ alias_name VARCHAR(50),
+ parent_category_id BIGINT,
+ business_name VARCHAR(50),
+ tenant_goods_business_id BIGINT,
+ category_level INTEGER,
+ is_leaf INTEGER,
+ open_salesman INTEGER,
+ sort_order INTEGER,
+ is_warehousing INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (category_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_goods_category IS 'DWD 维度表:dim_goods_category。ODS 来源表:billiards_ods.stock_goods_category_tree(对应 JSON:stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350533(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - tenant_id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】槟榔(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - category_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - category_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.alias_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - alias_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - alias_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.parent_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - pid。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - pid。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.business_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】槟榔(名称字段,用于展示与辅助识别)。 【ODS来源】stock_goods_category_tree - business_name。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - business_name。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.tenant_goods_business_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528317766(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】stock_goods_category_tree - tenant_goods_business_id。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.category_level IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - CASE WHEN pid = 0 THEN 1 ELSE 2 END。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN pid = 0 THEN 1 ELSE 2 END。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.is_leaf IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】stock_goods_category_tree - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.open_salesman IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - open_salesman。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - open_salesman。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.sort_order IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】stock_goods_category_tree - sort。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - sort。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.is_warehousing IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】stock_goods_category_tree - is_warehousing。 【JSON字段】stock_goods_category_tree.json - data.goodsCategoryList - is_warehousing。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_goods_category.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】stock_goods_category_tree - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
+ groupbuy_package_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ package_name VARCHAR(200),
+ package_template_id BIGINT,
+ selling_price NUMERIC(10,2),
+ coupon_face_value NUMERIC(10,2),
+ duration_seconds INTEGER,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ table_area_name VARCHAR(100),
+ is_enabled INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ tenant_table_area_id_list VARCHAR(512),
+ card_type_ids VARCHAR(255),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_groupbuy_package IS 'DWD 维度表:dim_groupbuy_package。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.groupbuy_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2939215004469573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - id。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - tenant_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - site_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.package_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】早场特惠一小时(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - package_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.package_template_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1814707240811572(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - package_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - package_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.selling_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_packages - selling_price。 【JSON字段】group_buy_packages.json - data.packageCouponList - selling_price。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.coupon_face_value IS '【说明】维度字段,用于补充维度属性。 【示例】0.0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - coupon_money。 【JSON字段】group_buy_packages.json - data.packageCouponList - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.duration_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_packages - duration。 【JSON字段】group_buy_packages.json - data.packageCouponList - duration。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-27 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - start_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2026-10-28 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - end_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - table_area_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.is_enabled IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_packages - is_enabled。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_enabled。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_packages - is_delete。 【JSON字段】group_buy_packages.json - data.packageCouponList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-10-27 18:24:09(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_packages - create_time。 【JSON字段】group_buy_packages.json - data.packageCouponList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.tenant_table_area_id_list IS '【说明】维度字段,用于补充维度属性。 【示例】2791960001957765(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - tenant_table_area_id_list。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id_list。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.card_type_ids IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - card_type_ids。 【JSON字段】group_buy_packages.json - data.packageCouponList - card_type_ids。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
+ groupbuy_package_id BIGINT,
+ site_name VARCHAR(100),
+ usable_count INTEGER,
+ date_type INTEGER,
+ usable_range VARCHAR(255),
+ date_info VARCHAR(255),
+ start_clock VARCHAR(16),
+ end_clock VARCHAR(16),
+ add_start_clock VARCHAR(16),
+ add_end_clock VARCHAR(16),
+ area_tag_type INTEGER,
+ table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_area_id_list VARCHAR(512),
+ group_type INTEGER,
+ system_group_type INTEGER,
+ package_type INTEGER,
+ effective_status INTEGER,
+ max_selectable_categories INTEGER,
+ creator_name VARCHAR(100),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dim_groupbuy_package_ex IS 'DWD 维度表(扩展字段表):dim_groupbuy_package_ex。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.groupbuy_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2939215004469573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - id。 【JSON字段】group_buy_packages.json - data.packageCouponList - id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - site_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - site_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.usable_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】9999999(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_packages - usable_count。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_count。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.date_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - date_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.usable_range IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - usable_range。 【JSON字段】group_buy_packages.json - data.packageCouponList - usable_range。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.date_info IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - date_info。 【JSON字段】group_buy_packages.json - data.packageCouponList - date_info。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.start_clock IS '【说明】维度字段,用于补充维度属性。 【示例】00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - start_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - start_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.end_clock IS '【说明】维度字段,用于补充维度属性。 【示例】1.00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - end_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - end_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.add_start_clock IS '【说明】维度字段,用于补充维度属性。 【示例】00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - add_start_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_start_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.add_end_clock IS '【说明】维度字段,用于补充维度属性。 【示例】1.00:00:00(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - add_end_clock。 【JSON字段】group_buy_packages.json - data.packageCouponList - add_end_clock。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.area_tag_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - area_tag_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - area_tag_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - table_area_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_packages - tenant_table_area_id。 【JSON字段】group_buy_packages.json - data.packageCouponList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.table_area_id_list IS '【说明】维度字段,用于补充维度属性。 【示例】NULL(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - table_area_id_list。 【JSON字段】group_buy_packages.json - data.packageCouponList - table_area_id_list。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.group_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - group_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - group_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.system_group_type IS '【说明】维度字段,用于补充维度属性。 【示例】1(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - system_group_type。 【JSON字段】group_buy_packages.json - data.packageCouponList - system_group_type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.package_type IS '【说明】维度字段,用于补充维度属性。 【示例】2(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - type。 【JSON字段】group_buy_packages.json - data.packageCouponList - type。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.effective_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】group_buy_packages - effective_status。 【JSON字段】group_buy_packages.json - data.packageCouponList - effective_status。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.max_selectable_categories IS '【说明】维度字段,用于补充维度属性。 【示例】0(维度字段,用于补充维度属性)。 【ODS来源】group_buy_packages - max_selectable_categories。 【JSON字段】group_buy_packages.json - data.packageCouponList - max_selectable_categories。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.creator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】店长:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_packages - creator_name。 【JSON字段】group_buy_packages.json - data.packageCouponList - creator_name。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_start_time IS '【说明】SCD2 开始时间(版本生效起点),用于维度慢变追踪。 【示例】2025-11-10T00:00:00+08:00(SCD2 开始时间(版本生效起点),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_end_time IS '【说明】SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。 【示例】9999-12-31T00:00:00+00:00(SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_is_current IS '【说明】SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。 【示例】1(SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+COMMENT ON COLUMN billiards_dwd.dim_groupbuy_package_ex.scd2_version IS '【说明】SCD2 版本号(自增),用于与时间段一起避免版本重叠。 【示例】1(SCD2 版本号(自增),用于与时间段一起避免版本重叠)。 【ODS来源】group_buy_packages - 无(DWD慢变元数据)。 【JSON字段】无 - DWD慢变元数据 - 无。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_settlement_head (
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_name VARCHAR(100),
+ table_id BIGINT,
+ settle_name VARCHAR(100),
+ order_trade_no BIGINT,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ settle_type INTEGER,
+ revoke_order_id BIGINT,
+ member_id BIGINT,
+ member_name VARCHAR(100),
+ member_phone VARCHAR(50),
+ member_card_account_id BIGINT,
+ member_card_type_name VARCHAR(100),
+ is_bind_member BOOLEAN,
+ member_discount_amount NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ pay_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ PRIMARY KEY (order_settle_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_settlement_head IS 'DWD 明细事实表:dwd_settlement_head。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - id。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tenantid。 【JSON字段】settlement_records.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - siteid。 【JSON字段】settlement_records.json - $ - siteid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - sitename。 【JSON字段】settlement_records.json - $ - sitename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tableid。 【JSON字段】settlement_records.json - $ - tableid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.settle_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - settlename。 【JSON字段】settlement_records.json - $ - settlename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - settlerelateid。 【JSON字段】settlement_records.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - createtime。 【JSON字段】settlement_records.json - $ - createtime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - paytime。 【JSON字段】settlement_records.json - $ - paytime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.settle_type IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - settletype。 【JSON字段】settlement_records.json - $ - settletype。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.revoke_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - revokeorderid。 【JSON字段】settlement_records.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - memberid。 【JSON字段】settlement_records.json - $ - memberid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - membername。 【JSON字段】settlement_records.json - $ - membername。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_phone IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - memberphone。 【JSON字段】settlement_records.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_card_account_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - tenantmembercardid。 【JSON字段】settlement_records.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - membercardtypename。 【JSON字段】settlement_records.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.is_bind_member IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isbindmember。 【JSON字段】settlement_records.json - $ - isbindmember。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - memberdiscountamount。 【JSON字段】settlement_records.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.consume_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - consumemoney。 【JSON字段】settlement_records.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - tablechargemoney。 【JSON字段】settlement_records.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - goodsmoney。 【JSON字段】settlement_records.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - realgoodsmoney。 【JSON字段】settlement_records.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.assistant_pd_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantpdmoney。 【JSON字段】settlement_records.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.assistant_cx_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantcxmoney。 【JSON字段】settlement_records.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - adjustamount。 【JSON字段】settlement_records.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - payamount。 【JSON字段】settlement_records.json - $ - payamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.balance_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - balanceamount。 【JSON字段】settlement_records.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.recharge_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - rechargecardamount。 【JSON字段】settlement_records.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.gift_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - giftcardamount。 【JSON字段】settlement_records.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.coupon_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - couponamount。 【JSON字段】settlement_records.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.rounding_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - roundingamount。 【JSON字段】settlement_records.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head.point_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointamount。 【JSON字段】settlement_records.json - $ - pointamount。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
+ order_settle_id BIGINT,
+ serial_number INTEGER,
+ settle_status INTEGER,
+ can_be_revoked BOOLEAN,
+ revoke_order_name VARCHAR(100),
+ revoke_time TIMESTAMPTZ,
+ is_first_order BOOLEAN,
+ service_money NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ payment_method INTEGER,
+ coupon_sale_amount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ is_activity BOOLEAN,
+ operator_name VARCHAR(100),
+ salesman_name VARCHAR(100),
+ order_remark VARCHAR(255),
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ PRIMARY KEY (order_settle_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_settlement_head_ex IS 'DWD 明细事实表(扩展字段表):dwd_settlement_head_ex。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - id。 【JSON字段】settlement_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - serialnumber。 【JSON字段】settlement_records.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.settle_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】NULL(状态枚举字段,用于标识业务状态)。 【ODS来源】settlement_records - settlestatus。 【JSON字段】settlement_records.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.can_be_revoked IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - canberevoked(派生:BOOLEAN(canberevoked))。 【JSON字段】settlement_records.json - $ - canberevoked(派生:BOOLEAN(canberevoked))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.revoke_order_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - revokeordername。 【JSON字段】settlement_records.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.revoke_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】settlement_records - revoketime。 【JSON字段】settlement_records.json - $ - revoketime。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_first_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isfirst(派生:BOOLEAN(isfirst))。 【JSON字段】settlement_records.json - $ - isfirst(派生:BOOLEAN(isfirst))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - servicemoney。 【JSON字段】settlement_records.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.cash_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - cashamount。 【JSON字段】settlement_records.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - cardamount。 【JSON字段】settlement_records.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.online_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - onlineamount。 【JSON字段】settlement_records.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - refundamount。 【JSON字段】settlement_records.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.prepay_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - prepaymoney。 【JSON字段】settlement_records.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - paymentmethod。 【JSON字段】settlement_records.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.coupon_sale_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - couponsaleamount。 【JSON字段】settlement_records.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.all_coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - allcoupondiscount。 【JSON字段】settlement_records.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - goodspromotionmoney。 【JSON字段】settlement_records.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - assistantpromotionmoney。 【JSON字段】settlement_records.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.activity_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - activitydiscount。 【JSON字段】settlement_records.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.assistant_manual_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - assistantmanualdiscount。 【JSON字段】settlement_records.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.point_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointdiscountprice。 【JSON字段】settlement_records.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.point_discount_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】settlement_records - pointdiscountcost。 【JSON字段】settlement_records.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_use_coupon IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isusecoupon(派生:BOOLEAN(isusecoupon))。 【JSON字段】settlement_records.json - $ - isusecoupon(派生:BOOLEAN(isusecoupon))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_use_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】settlement_records - isusediscount(派生:BOOLEAN(isusediscount))。 【JSON字段】settlement_records.json - $ - isusediscount(派生:BOOLEAN(isusediscount))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.is_activity IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】settlement_records - isactivity(派生:BOOLEAN(isactivity))。 【JSON字段】settlement_records.json - $ - isactivity(派生:BOOLEAN(isactivity))。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - operatorname。 【JSON字段】settlement_records.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】settlement_records - salesmanname。 【JSON字段】settlement_records.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.order_remark IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】settlement_records - orderremark。 【JSON字段】settlement_records.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - operatorid。 【JSON字段】settlement_records.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_dwd.dwd_settlement_head_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】settlement_records - salesmanuserid。 【JSON字段】settlement_records.json - $ - salesmanuserid。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
+ table_fee_log_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ member_id BIGINT,
+ ledger_name VARCHAR(64),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ real_table_charge_money NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ real_table_use_seconds INTEGER,
+ add_clock_seconds INTEGER,
+ start_use_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (table_fee_log_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_log IS 'DWD 明细事实表:dwd_table_fee_log。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.table_fee_log_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029058885(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】table_fee_transactions - order_trade_no。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - order_settle_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - order_pay_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - tenant_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_table_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963794329671(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - site_table_area_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.site_table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - site_table_area_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791960001957765(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - tenant_table_area_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - member_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A17(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - ledger_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - ledger_unit_price。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - ledger_count。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - ledger_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.real_table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - real_table_charge_money。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_charge_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.coupon_promotion_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - coupon_promotion_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - coupon_promotion_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - member_discount_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - adjust_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - adjust_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.real_table_use_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - real_table_use_seconds。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - real_table_use_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.add_clock_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_transactions - add_clock_seconds。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - add_clock_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.start_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - start_use_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - start_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - ledger_end_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_end_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - create_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】table_fee_transactions - ledger_status。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_transactions - is_single_order。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_transactions - is_delete。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - is_delete。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
+ table_fee_log_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_name VARCHAR(64),
+ used_card_amount NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ ledger_start_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ salesman_org_id BIGINT,
+ PRIMARY KEY (table_fee_log_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_log_ex IS 'DWD 明细事实表(扩展字段表):dwd_table_fee_log_ex。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.table_fee_log_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029058885(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - operator_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_transactions - salesman_name。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.used_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - used_card_amount。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - used_card_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - service_money。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - service_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.mgmt_fee IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - mgmt_fee。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - mgmt_fee。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.fee_total IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_transactions - fee_total。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - fee_total。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.ledger_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - ledger_start_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - ledger_start_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.last_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:28:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_transactions - last_use_time。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - last_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - operator_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - salesman_user_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_log_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_transactions - salesman_org_id。 【JSON字段】table_fee_transactions.json - data.siteTableUseDetailsList - salesman_org_id。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
+ table_fee_adjust_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ ledger_amount NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ adjust_time TIMESTAMPTZ,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_adjust IS 'DWD 明细事实表:dwd_table_fee_adjust。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_fee_adjust_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441881989(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957784612605829(明细字段,用于记录事实取值)。 【ODS来源】table_fee_discount_records - order_trade_no。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913171693253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - order_settle_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - site_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793020259897413(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - site_table_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791961347968901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_table_area_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - tableprofile.table_area_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tableprofile.table_area_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791961347968901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - tenant_table_area_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】148.15(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】table_fee_discount_records - ledger_amount。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】table_fee_discount_records - ledger_status。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】table_fee_discount_records - is_delete。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust.adjust_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:25:11(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】table_fee_discount_records - create_time。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - create_time。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
+ table_fee_adjust_id BIGINT,
+ adjust_type INTEGER,
+ ledger_count INTEGER,
+ ledger_name VARCHAR(128),
+ applicant_name VARCHAR(64),
+ operator_name VARCHAR(64),
+ applicant_id BIGINT,
+ operator_id BIGINT,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_table_fee_adjust_ex IS 'DWD 明细事实表(扩展字段表):dwd_table_fee_adjust_ex。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.table_fee_adjust_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441881989(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.adjust_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】table_fee_discount_records - adjust_type。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - adjust_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】table_fee_discount_records - ledger_count。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - ledger_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.applicant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - applicant_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】table_fee_discount_records - operator_name。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.applicant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - applicant_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - applicant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_table_fee_adjust_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】table_fee_discount_records - operator_id。 【JSON字段】table_fee_discount_records.json - data.taiFeeAdjustInfos - operator_id。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
+ store_goods_sale_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_goods_id BIGINT,
+ site_id BIGINT,
+ tenant_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ site_table_id BIGINT,
+ ledger_name VARCHAR(200),
+ ledger_group_name VARCHAR(100),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (store_goods_sale_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_store_goods_sale IS 'DWD 明细事实表:dwd_store_goods_sale。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.store_goods_sale_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029550406(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - order_trade_no。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_settle_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_pay_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.order_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858456391557(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793026176012357(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792115932417925(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_category_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528350540(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_category_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_category_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.tenant_goods_business_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683528317768(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - tenant_goods_business_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_table_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】哇哈哈矿泉水(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - ledger_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】酒水(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - ledger_group_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_group_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - ledger_unit_price。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_sales_records - ledger_count。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - ledger_amount。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - real_goods_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - real_goods_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.cost_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.01(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - cost_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - cost_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】store_goods_sales_records - ledger_status。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_sales_records - is_delete。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】store_goods_sales_records - create_time。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - create_time。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
+ store_goods_sale_id BIGINT,
+ legacy_order_goods_id BIGINT,
+ site_name TEXT,
+ legacy_site_id BIGINT,
+ goods_remark TEXT,
+ option_value_name TEXT,
+ operator_name TEXT,
+ open_salesman_flag INTEGER,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ discount_money NUMERIC(18,2),
+ returns_number INTEGER,
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ package_coupon_id BIGINT,
+ order_coupon_id BIGINT,
+ member_coupon_id BIGINT,
+ option_price NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ is_single_order INTEGER,
+ sales_type INTEGER,
+ operator_id BIGINT,
+ PRIMARY KEY (store_goods_sale_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_store_goods_sale_ex IS 'DWD 明细事实表(扩展字段表):dwd_store_goods_sale_ex。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.store_goods_sale_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029550406(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.legacy_order_goods_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858456391557(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_goods_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - siteName。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - siteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.legacy_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - site_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.goods_remark IS '【说明】明细字段,用于记录事实取值。 【示例】哇哈哈矿泉水(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - goods_remark。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - goods_remark。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_value_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - option_value_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_value_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - operator_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.open_salesman_flag IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - openSalesman。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - openSalesman。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - salesman_user_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】store_goods_sales_records - salesman_name。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - salesman_role_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - salesman_role_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - sales_man_org_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_man_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.returns_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】0(数量/时长字段,用于统计与计量)。 【ODS来源】store_goods_sales_records - returns_number。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - returns_number。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - coupon_deduct_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - member_discount_amount。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.point_discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - point_discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.point_discount_money_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - point_discount_money_cost。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - point_discount_money_cost。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.package_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - package_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - package_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.order_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - order_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - order_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.member_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - member_coupon_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - member_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_price。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_member_discount_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_member_discount_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_member_discount_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.option_coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - option_coupon_deduct_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - option_coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.push_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】store_goods_sales_records - push_money。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - push_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】store_goods_sales_records - is_single_order。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.sales_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】store_goods_sales_records - sales_type。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - sales_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_store_goods_sale_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】store_goods_sales_records - operator_id。 【JSON字段】store_goods_sales_records.json - data.orderGoodsLedgers - operator_id。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
+ assistant_service_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INTEGER,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ assistant_no VARCHAR(64),
+ nickname VARCHAR(64),
+ site_assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ person_org_id BIGINT,
+ assistant_level INTEGER,
+ level_name VARCHAR(64),
+ skill_id BIGINT,
+ skill_name VARCHAR(64),
+ ledger_unit_price NUMERIC(10,2),
+ ledger_amount NUMERIC(10,2),
+ projected_income NUMERIC(10,2),
+ coupon_deduct_money NUMERIC(10,2),
+ income_seconds INTEGER,
+ real_use_seconds INTEGER,
+ add_clock INTEGER,
+ create_time TIMESTAMPTZ,
+ start_use_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ PRIMARY KEY (assistant_service_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_assistant_service_log IS 'DWD 明细事实表:dwd_assistant_service_log。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_service_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441292165(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957784612605829(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - order_trade_no。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913171693253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_settle_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_pay_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957788717240005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_assistant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.order_assistant_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - order_assistant_type。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - tenant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - site_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793020259897413(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - site_table_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - site_table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - tenant_member_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - system_member_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_no IS '【说明】明细字段,用于记录事实取值。 【示例】27(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - assistantNo。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantNo。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.nickname IS '【说明】名称字段,用于展示与辅助识别。 【示例】泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - nickname。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - nickname。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.site_assistant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957788717240005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - order_assistant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2946266868976453(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - user_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_team_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2792011585884037(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - assistant_team_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_team_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.person_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2946266869336901(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - person_org_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - person_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.assistant_level IS '【说明】明细字段,用于记录事实取值。 【示例】10(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - assistant_level。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistant_level。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.level_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】初级(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - levelName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - levelName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.skill_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683529513797(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - skill_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.skill_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】基础课(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - skillName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skillName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】98.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - ledger_unit_price。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】206.67(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - ledger_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.projected_income IS '【说明】明细字段,用于记录事实取值。 【示例】168.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - projected_income。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - projected_income。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.coupon_deduct_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - coupon_deduct_money。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - coupon_deduct_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.income_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】7560(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - income_seconds。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - income_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.real_use_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】7592(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - real_use_seconds。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - real_use_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.add_clock IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - add_clock。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - add_clock。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:25:11(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - create_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.start_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 21:18:18(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - start_use_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - start_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.last_use_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:24:50(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - last_use_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - last_use_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_delete。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_delete。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
+ assistant_service_id BIGINT,
+ table_name VARCHAR(64),
+ assistant_name VARCHAR(64),
+ ledger_name VARCHAR(128),
+ ledger_group_name VARCHAR(128),
+ ledger_count INTEGER,
+ member_discount_amount NUMERIC(10,2),
+ manual_discount_amount NUMERIC(10,2),
+ service_money NUMERIC(10,2),
+ returns_clock INTEGER,
+ ledger_start_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_confirm INTEGER,
+ is_single_order INTEGER,
+ is_not_responding INTEGER,
+ is_trash INTEGER,
+ trash_applicant_id BIGINT,
+ trash_applicant_name VARCHAR(64),
+ trash_reason VARCHAR(255),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_org_id BIGINT,
+ skill_grade INTEGER,
+ service_grade INTEGER,
+ composite_grade NUMERIC(5,2),
+ sum_grade NUMERIC(10,2),
+ get_grade_times INTEGER,
+ grade_status INTEGER,
+ composite_grade_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_service_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_assistant_service_log_ex IS 'DWD 明细事实表(扩展字段表):dwd_assistant_service_log_ex。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.assistant_service_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957913441292165(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】S1(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - tableName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.assistant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】何海婷(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - assistantName。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】27-泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - ledger_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - ledger_group_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_group_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】7592(数量/时长字段,用于统计与计量)。 【ODS来源】assistant_service_records - ledger_count。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - member_discount_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - member_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.manual_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - manual_discount_amount。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - manual_discount_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_service_records - service_money。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.returns_clock IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - returns_clock。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - returns_clock。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_start_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 21:18:18(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - ledger_start_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_start_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_end_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:24:50(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - ledger_end_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_end_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_service_records - ledger_status。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_confirm IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】2(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_confirm。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_confirm。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_single_order。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_not_responding IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_not_responding。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_not_responding。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.is_trash IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】assistant_service_records - is_trash。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - is_trash。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_applicant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - trash_applicant_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_applicant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - trash_applicant_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_applicant_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.trash_reason IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - trash_reason。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - trash_reason。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - salesman_user_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_service_records - salesman_name。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_service_records - salesman_org_id。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - salesman_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.skill_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - skill_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - skill_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.service_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - service_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - service_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.composite_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - composite_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.sum_grade IS '【说明】明细字段,用于记录事实取值。 【示例】0.0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - sum_grade。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - sum_grade。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.get_grade_times IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】assistant_service_records - get_grade_times。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - get_grade_times。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.grade_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】assistant_service_records - grade_status。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - grade_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_service_log_ex.composite_grade_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0001-01-01 00:00:00(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_service_records - composite_grade_time。 【JSON字段】assistant_service_records.json - data.orderAssistantDetails - composite_grade_time。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
+ assistant_trash_event_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ assistant_no VARCHAR(32),
+ assistant_name VARCHAR(64),
+ charge_minutes_raw INTEGER,
+ abolish_amount NUMERIC(18,2),
+ trash_reason VARCHAR(255),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_trash_event_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_assistant_trash_event IS 'DWD 明细事实表:dwd_assistant_trash_event。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_trash_event_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957675849518789(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - id。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - siteId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - siteId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793016660660357(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - tableId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791963816579205(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - tableAreaId。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableAreaId。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_no IS '【说明】明细字段,用于记录事实取值。 【示例】泡芙(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - assistantName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.assistant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】泡芙(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - assistantName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.charge_minutes_raw IS '【说明】明细字段,用于记录事实取值。 【示例】214(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - pdChargeMinutes。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - pdChargeMinutes。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.abolish_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】5.83(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】assistant_cancellation_records - assistantAbolishAmount。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - assistantAbolishAmount。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.trash_reason IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】assistant_cancellation_records - trashReason。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - trashReason。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 19:23:29(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】assistant_cancellation_records - createTime。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - createTime。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event_Ex (
+ assistant_trash_event_id BIGINT,
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ PRIMARY KEY (assistant_trash_event_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_assistant_trash_event_ex IS 'DWD 明细事实表(扩展字段表):dwd_assistant_trash_event_ex。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.assistant_trash_event_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957675849518789(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】assistant_cancellation_records - id。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】C1(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - tableName。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_assistant_trash_event_ex.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】C区(名称字段,用于展示与辅助识别)。 【ODS来源】assistant_cancellation_records - tableArea。 【JSON字段】assistant_cancellation_records.json - data.abolitionAssistants - tableArea。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
+ balance_change_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ card_type_id BIGINT,
+ card_type_name VARCHAR(32),
+ member_name VARCHAR(64),
+ member_mobile VARCHAR(20),
+ balance_before NUMERIC(18,2),
+ change_amount NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ from_type INTEGER,
+ payment_method INTEGER,
+ change_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ remark VARCHAR(255),
+ PRIMARY KEY (balance_change_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_member_balance_change IS 'DWD 明细事实表:dwd_member_balance_change。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_change_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957881605869253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - site_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.register_site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - register_site_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - register_site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799212845565701(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_member_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.system_member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799212844549893(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - system_member_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - system_member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.tenant_member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2799219999295237(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - tenant_member_card_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_card_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.card_type_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793249295533893(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - card_type_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - card_type_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】储值卡(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - memberCardTypeName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberCardTypeName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.member_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】曾丹烨(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - memberName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.member_mobile IS '【说明】明细字段,用于记录事实取值。 【示例】13922213242(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - memberMobile。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - memberMobile。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_before IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】816.3(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - before。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - before。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.change_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】-120.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - account_data。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - account_data。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.balance_after IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】696.3(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - after。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - after。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.from_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - from_type。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - from_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - payment_method。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.change_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 22:52:48(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】member_balance_changes - create_time。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】member_balance_changes - is_delete。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change.remark IS '【说明】明细字段,用于记录事实取值。 【示例】充值退款(明细字段,用于记录事实取值)。 【ODS来源】member_balance_changes - remark。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - remark。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
+ balance_change_id BIGINT,
+ pay_site_name VARCHAR(64),
+ register_site_name VARCHAR(64),
+ refund_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ PRIMARY KEY (balance_change_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_member_balance_change_ex IS 'DWD 明细事实表(扩展字段表):dwd_member_balance_change_ex。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.balance_change_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957881605869253(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.pay_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - paySiteName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - paySiteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.register_site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - registerSiteName。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - registerSiteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】member_balance_changes - refund_amount。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - refund_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】member_balance_changes - operator_id。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_member_balance_change_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】member_balance_changes - operator_name。 【JSON字段】member_balance_changes.json - data.tenantMemberCardLogs - operator_name。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
+ redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_charge_seconds INTEGER,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_coupon_id BIGINT,
+ coupon_origin_id BIGINT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ order_coupon_channel INTEGER,
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ promotion_seconds INTEGER,
+ coupon_code VARCHAR(64),
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ ledger_name VARCHAR(128),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (redemption_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_groupbuy_redemption IS 'DWD 明细事实表:dwd_groupbuy_redemption。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029615941(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - tenant_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - site_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793003705192517(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - table_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.tenant_table_area_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2791960001957765(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - tenant_table_area_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_table_area_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.table_charge_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - table_charge_seconds。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_charge_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_trade_no IS '【说明】明细字段,用于记录事实取值。 【示例】2957858167230149(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - order_trade_no。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_trade_no。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_settle_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_settle_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_settle_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858168229573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_coupon_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_origin_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858168229573(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - coupon_origin_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_origin_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_activity_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957858166460101(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - promotion_activity_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_activity_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_coupon_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2798727423528005(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - promotion_coupon_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_coupon_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.order_coupon_channel IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - order_coupon_channel。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_unit_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】29.9(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - ledger_unit_price。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_unit_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_count IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - ledger_count。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_count。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - ledger_amount。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - coupon_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.promotion_seconds IS '【说明】数量/时长字段,用于统计与计量。 【示例】3600(数量/时长字段,用于统计与计量)。 【ODS来源】group_buy_redemption_records - promotion_seconds。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_seconds。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.coupon_code IS '【说明】明细字段,用于记录事实取值。 【示例】0107892475999(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - coupon_code。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_code。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.is_single_order IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】1(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_redemption_records - is_single_order。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_single_order。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】group_buy_redemption_records - is_delete。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】全天A区中八一小时(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - ledger_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】group_buy_redemption_records - create_time。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - create_time。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
+ redemption_id BIGINT,
+ site_name VARCHAR(64),
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ order_pay_id BIGINT,
+ goods_option_price NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ offer_type INTEGER,
+ ledger_status INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ ledger_group_name VARCHAR(128),
+ PRIMARY KEY (redemption_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_groupbuy_redemption_ex IS 'DWD 明细事实表(扩展字段表):dwd_groupbuy_redemption_ex。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924029615941(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.site_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - siteName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - siteName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A17(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - tableName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_area_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】A区(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - tableAreaName。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - tableAreaName。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.order_pay_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - order_pay_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - order_pay_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.goods_option_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - goodsOptionPrice。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goodsOptionPrice。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - goods_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - goods_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.table_service_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - table_service_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - table_service_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - assistant_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.assistant_service_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - assistant_service_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - assistant_service_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.reward_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - reward_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - reward_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.recharge_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】group_buy_redemption_records - recharge_promotion_money。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - recharge_promotion_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.offer_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】group_buy_redemption_records - offer_type。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - offer_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.ledger_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】group_buy_redemption_records - ledger_status。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - operator_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - operator_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - operator_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - salesman_user_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_user_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - salesman_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - salesman_role_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - salesman_role_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.salesman_org_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】group_buy_redemption_records - sales_man_org_id。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - sales_man_org_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_groupbuy_redemption_ex.ledger_group_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】group_buy_redemption_records - ledger_group_name。 【JSON字段】group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_group_name。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
+ platform_coupon_redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ coupon_code VARCHAR(64),
+ coupon_channel INTEGER,
+ coupon_name VARCHAR(200),
+ sale_price NUMERIC(10,2),
+ coupon_money NUMERIC(10,2),
+ coupon_free_time INTEGER,
+ channel_deal_id BIGINT,
+ deal_id BIGINT,
+ group_package_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ certificate_id VARCHAR(64),
+ verify_id VARCHAR(64),
+ use_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ consume_time TIMESTAMPTZ,
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_platform_coupon_redemption IS 'DWD 明细事实表:dwd_platform_coupon_redemption。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929042218501(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - id。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - tenant_id。 【JSON字段】platform_coupon_redemption_records.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - site_id。 【JSON字段】platform_coupon_redemption_records.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_code IS '【说明】明细字段,用于记录事实取值。 【示例】0102701209726(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_code。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_code。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_channel IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_channel。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】【全天可用】中八桌球一小时(A区)(名称字段,用于展示与辅助识别)。 【ODS来源】platform_coupon_redemption_records - coupon_name。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_name。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.sale_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】29.9(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】platform_coupon_redemption_records - sale_price。 【JSON字段】platform_coupon_redemption_records.json - $ - sale_price。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】48.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】platform_coupon_redemption_records - coupon_money。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_money。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.coupon_free_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】0(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - coupon_free_time。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_free_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.channel_deal_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1128411555(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - channel_deal_id。 【JSON字段】platform_coupon_redemption_records.json - $ - channel_deal_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.deal_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】1345108507(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - deal_id。 【JSON字段】platform_coupon_redemption_records.json - $ - deal_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.group_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - group_package_id。 【JSON字段】platform_coupon_redemption_records.json - $ - group_package_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.site_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929043037702(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - site_order_id。 【JSON字段】platform_coupon_redemption_records.json - $ - site_order_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2793001904918661(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - table_id。 【JSON字段】platform_coupon_redemption_records.json - $ - table_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.certificate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】5008024789379597447(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - certificate_id。 【JSON字段】platform_coupon_redemption_records.json - $ - certificate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.verify_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】7570689090418149418(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - verify_id。 【JSON字段】platform_coupon_redemption_records.json - $ - verify_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.use_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】platform_coupon_redemption_records - use_status。 【JSON字段】platform_coupon_redemption_records.json - $ - use_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】platform_coupon_redemption_records - is_delete。 【JSON字段】platform_coupon_redemption_records.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:41:03(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - create_time。 【JSON字段】platform_coupon_redemption_records.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption.consume_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:41:04(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】platform_coupon_redemption_records - consume_time。 【JSON字段】platform_coupon_redemption_records.json - $ - consume_time。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
+ platform_coupon_redemption_id BIGINT,
+ coupon_cover VARCHAR(255),
+ coupon_remark VARCHAR(255),
+ groupon_type INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(50),
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_platform_coupon_redemption_ex IS 'DWD 明细事实表(扩展字段表):dwd_platform_coupon_redemption_ex。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.platform_coupon_redemption_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957929042218501(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - id。 【JSON字段】platform_coupon_redemption_records.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.coupon_cover IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_cover。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_cover。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.coupon_remark IS '【说明】明细字段,用于记录事实取值。 【示例】617547ec-9697-4f58-a700-b30a49e88904||CgYIASAHKAESLgos9ZhHDryhHb0z3RpdBZ0dVoaQbkldBcx/XTXPV8Te+9SEqYOa7aDp8nbKOpsaAA==(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - coupon_remark。 【JSON字段】platform_coupon_redemption_records.json - $ - coupon_remark。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.groupon_type IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】platform_coupon_redemption_records - groupon_type。 【JSON字段】platform_coupon_redemption_records.json - $ - groupon_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790687322443013(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】platform_coupon_redemption_records - operator_id。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_platform_coupon_redemption_ex.operator_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】收银员:郑丽珊(名称字段,用于展示与辅助识别)。 【ODS来源】platform_coupon_redemption_records - operator_name。 【JSON字段】platform_coupon_redemption_records.json - $ - operator_name。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_recharge_order (
+ recharge_order_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ member_id BIGINT,
+ member_name_snapshot TEXT,
+ member_phone_snapshot TEXT,
+ tenant_member_card_id BIGINT,
+ member_card_type_name TEXT,
+ settle_relate_id BIGINT,
+ settle_type INTEGER,
+ settle_name TEXT,
+ is_first INTEGER,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ payment_method INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_recharge_order IS 'DWD 明细事实表:dwd_recharge_order。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.recharge_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - id。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tenantid。 【JSON字段】recharge_settlements.json - $ - tenantid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - siteid。 【JSON字段】recharge_settlements.json - $ - siteid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - memberid。 【JSON字段】recharge_settlements.json - $ - memberid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - membername。 【JSON字段】recharge_settlements.json - $ - membername。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_phone_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - memberphone。 【JSON字段】recharge_settlements.json - $ - memberphone。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.tenant_member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tenantmembercardid。 【JSON字段】recharge_settlements.json - $ - tenantmembercardid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.member_card_type_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - membercardtypename。 【JSON字段】recharge_settlements.json - $ - membercardtypename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - settlerelateid。 【JSON字段】recharge_settlements.json - $ - settlerelateid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_type IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - settletype。 【JSON字段】recharge_settlements.json - $ - settletype。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.settle_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - settlename。 【JSON字段】recharge_settlements.json - $ - settlename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.is_first IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isfirst。 【JSON字段】recharge_settlements.json - $ - isfirst。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - payamount。 【JSON字段】recharge_settlements.json - $ - payamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - refundamount。 【JSON字段】recharge_settlements.json - $ - refundamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.point_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointamount。 【JSON字段】recharge_settlements.json - $ - pointamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.cash_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - cashamount。 【JSON字段】recharge_settlements.json - $ - cashamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - paymentmethod。 【JSON字段】recharge_settlements.json - $ - paymentmethod。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - createtime。 【JSON字段】recharge_settlements.json - $ - createtime。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - paytime。 【JSON字段】recharge_settlements.json - $ - paytime。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
+ recharge_order_id BIGINT,
+ site_name_snapshot TEXT,
+ settle_status INTEGER,
+ is_bind_member BOOLEAN,
+ is_activity BOOLEAN,
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ can_be_revoked BOOLEAN,
+ online_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name_snapshot TEXT,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ order_remark TEXT,
+ table_id INTEGER,
+ serial_number INTEGER,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_recharge_order_ex IS 'DWD 明细事实表(扩展字段表):dwd_recharge_order_ex。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.recharge_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - id。 【JSON字段】recharge_settlements.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.site_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - sitename。 【JSON字段】recharge_settlements.json - $ - sitename。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.settle_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】NULL(状态枚举字段,用于标识业务状态)。 【ODS来源】recharge_settlements - settlestatus。 【JSON字段】recharge_settlements.json - $ - settlestatus。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_bind_member IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isbindmember(派生:BOOLEAN(isbindmember))。 【JSON字段】recharge_settlements.json - $ - isbindmember(派生:BOOLEAN(isbindmember))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_activity IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isactivity(派生:BOOLEAN(isactivity))。 【JSON字段】recharge_settlements.json - $ - isactivity(派生:BOOLEAN(isactivity))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_use_coupon IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - isusecoupon(派生:BOOLEAN(isusecoupon))。 【JSON字段】recharge_settlements.json - $ - isusecoupon(派生:BOOLEAN(isusecoupon))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.is_use_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - isusediscount(派生:BOOLEAN(isusediscount))。 【JSON字段】recharge_settlements.json - $ - isusediscount(派生:BOOLEAN(isusediscount))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.can_be_revoked IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】NULL(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】recharge_settlements - canberevoked(派生:BOOLEAN(canberevoked))。 【JSON字段】recharge_settlements.json - $ - canberevoked(派生:BOOLEAN(canberevoked))。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.online_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - onlineamount。 【JSON字段】recharge_settlements.json - $ - onlineamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.balance_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - balanceamount。 【JSON字段】recharge_settlements.json - $ - balanceamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - cardamount。 【JSON字段】recharge_settlements.json - $ - cardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.coupon_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - couponamount。 【JSON字段】recharge_settlements.json - $ - couponamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.recharge_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - rechargecardamount。 【JSON字段】recharge_settlements.json - $ - rechargecardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.gift_card_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - giftcardamount。 【JSON字段】recharge_settlements.json - $ - giftcardamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.prepay_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - prepaymoney。 【JSON字段】recharge_settlements.json - $ - prepaymoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.consume_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - consumemoney。 【JSON字段】recharge_settlements.json - $ - consumemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - goodsmoney。 【JSON字段】recharge_settlements.json - $ - goodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.real_goods_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - realgoodsmoney。 【JSON字段】recharge_settlements.json - $ - realgoodsmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.table_charge_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - tablechargemoney。 【JSON字段】recharge_settlements.json - $ - tablechargemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.service_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - servicemoney。 【JSON字段】recharge_settlements.json - $ - servicemoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.activity_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - activitydiscount。 【JSON字段】recharge_settlements.json - $ - activitydiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.all_coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - allcoupondiscount。 【JSON字段】recharge_settlements.json - $ - allcoupondiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.goods_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - goodspromotionmoney。 【JSON字段】recharge_settlements.json - $ - goodspromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_promotion_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantpromotionmoney。 【JSON字段】recharge_settlements.json - $ - assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_pd_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantpdmoney。 【JSON字段】recharge_settlements.json - $ - assistantpdmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_cx_money IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - assistantcxmoney。 【JSON字段】recharge_settlements.json - $ - assistantcxmoney。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.assistant_manual_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - assistantmanualdiscount。 【JSON字段】recharge_settlements.json - $ - assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.coupon_sale_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - couponsaleamount。 【JSON字段】recharge_settlements.json - $ - couponsaleamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.member_discount_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - memberdiscountamount。 【JSON字段】recharge_settlements.json - $ - memberdiscountamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.point_discount_price IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointdiscountprice。 【JSON字段】recharge_settlements.json - $ - pointdiscountprice。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.point_discount_cost IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - pointdiscountcost。 【JSON字段】recharge_settlements.json - $ - pointdiscountcost。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.adjust_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - adjustamount。 【JSON字段】recharge_settlements.json - $ - adjustamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.rounding_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】NULL(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】recharge_settlements - roundingamount。 【JSON字段】recharge_settlements.json - $ - roundingamount。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - operatorid。 【JSON字段】recharge_settlements.json - $ - operatorid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.operator_name_snapshot IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - operatorname。 【JSON字段】recharge_settlements.json - $ - operatorname。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.salesman_user_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - salesmanuserid。 【JSON字段】recharge_settlements.json - $ - salesmanuserid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.salesman_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - salesmanname。 【JSON字段】recharge_settlements.json - $ - salesmanname。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.order_remark IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】recharge_settlements - orderremark。 【JSON字段】recharge_settlements.json - $ - orderremark。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.table_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - tableid。 【JSON字段】recharge_settlements.json - $ - tableid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.serial_number IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【ODS来源】recharge_settlements - serialnumber。 【JSON字段】recharge_settlements.json - $ - serialnumber。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_order_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】recharge_settlements - revokeorderid。 【JSON字段】recharge_settlements.json - $ - revokeorderid。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_order_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【ODS来源】recharge_settlements - revokeordername。 【JSON字段】recharge_settlements.json - $ - revokeordername。';
+COMMENT ON COLUMN billiards_dwd.dwd_recharge_order_ex.revoke_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】NULL(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】recharge_settlements - revoketime。 【JSON字段】recharge_settlements.json - $ - revoketime。';
+
+
+CREATE TABLE IF NOT EXISTS dwd_payment (
+ payment_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ payment_method INTEGER,
+ online_pay_channel INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ pay_date DATE,
+ PRIMARY KEY (payment_id)
+);
+
+COMMENT ON TABLE billiards_dwd.dwd_payment IS 'DWD 明细事实表:dwd_payment。ODS 来源表:billiards_ods.payment_transactions(对应 JSON:payment_transactions.json;分析:payment_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.payment_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957924026486597(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - id。 【JSON字段】payment_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - site_id。 【JSON字段】payment_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.relate_type IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - relate_type。 【JSON字段】payment_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2957922914357125(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】payment_transactions - relate_id。 【JSON字段】payment_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】10.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】payment_transactions - pay_amount。 【JSON字段】payment_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】payment_transactions - pay_status。 【JSON字段】payment_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】4(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - payment_method。 【JSON字段】payment_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.online_pay_channel IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】payment_transactions - online_pay_channel。 【JSON字段】payment_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - create_time。 【JSON字段】payment_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - pay_time。 【JSON字段】payment_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_payment.pay_date IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-09 23:35:57(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】payment_transactions - pay_time(派生:DATE(pay_time))。 【JSON字段】payment_transactions.json - $ - pay_time(派生:DATE(pay_time))。';
+
+
+ CREATE TABLE IF NOT EXISTS dwd_refund (
+ refund_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ channel_fee NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ payment_method INTEGER,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ PRIMARY KEY (refund_id)
+ );
+
+COMMENT ON TABLE billiards_dwd.dwd_refund IS 'DWD 明细事实表:dwd_refund。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.refund_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955202296416389(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - id。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.tenant_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790683160709957(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - tenant_id。 【JSON字段】refund_transactions.json - $ - tenant_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.site_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2790685415443269(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - site_id。 【JSON字段】refund_transactions.json - $ - site_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.relate_type IS '【说明】明细字段,用于记录事实取值。 【示例】5(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - relate_type。 【JSON字段】refund_transactions.json - $ - relate_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.relate_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955078219057349(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - relate_id。 【JSON字段】refund_transactions.json - $ - relate_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.pay_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】-5000.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - pay_amount。 【JSON字段】refund_transactions.json - $ - pay_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.channel_fee IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - channel_fee。 【JSON字段】refund_transactions.json - $ - channel_fee。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.pay_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:27:16(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】refund_transactions - pay_time。 【JSON字段】refund_transactions.json - $ - pay_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.create_time IS '【说明】时间/日期字段,用于记录业务时间与统计口径对齐。 【示例】2025-11-08 01:27:16(时间/日期字段,用于记录业务时间与统计口径对齐)。 【ODS来源】refund_transactions - create_time。 【JSON字段】refund_transactions.json - $ - create_time。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.payment_method IS '【说明】明细字段,用于记录事实取值。 【示例】4(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - payment_method。 【JSON字段】refund_transactions.json - $ - payment_method。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.member_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - member_id。 【JSON字段】refund_transactions.json - $ - member_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund.member_card_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - member_card_id。 【JSON字段】refund_transactions.json - $ - member_card_id。';
+
+
+ CREATE TABLE IF NOT EXISTS dwd_refund_Ex (
+ refund_id BIGINT,
+ tenant_name VARCHAR(64),
+ pay_sn BIGINT,
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ action_type INTEGER,
+ is_revoke INTEGER,
+ is_delete INTEGER,
+ check_status INTEGER,
+ online_pay_channel INTEGER,
+ online_pay_type INTEGER,
+ pay_terminal INTEGER,
+ pay_config_id INTEGER,
+ cashier_point_id INTEGER,
+ operator_id BIGINT,
+ channel_payer_id VARCHAR(128),
+ channel_pay_no VARCHAR(128),
+ PRIMARY KEY (refund_id)
+ );
+
+COMMENT ON TABLE billiards_dwd.dwd_refund_ex IS 'DWD 明细事实表(扩展字段表):dwd_refund_ex。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.refund_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】2955202296416389(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - id。 【JSON字段】refund_transactions.json - $ - id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.tenant_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】朗朗桌球(名称字段,用于展示与辅助识别)。 【ODS来源】refund_transactions - tenantName。 【JSON字段】refund_transactions.json - $ - tenantName。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_sn IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - pay_sn。 【JSON字段】refund_transactions.json - $ - pay_sn。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.refund_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - refund_amount。 【JSON字段】refund_transactions.json - $ - refund_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.round_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - round_amount。 【JSON字段】refund_transactions.json - $ - round_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.balance_frozen_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - balance_frozen_amount。 【JSON字段】refund_transactions.json - $ - balance_frozen_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.card_frozen_amount IS '【说明】金额字段,用于计费/结算/核算等金额计算。 【示例】0.0(金额字段,用于计费/结算/核算等金额计算)。 【ODS来源】refund_transactions - card_frozen_amount。 【JSON字段】refund_transactions.json - $ - card_frozen_amount。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】2(状态枚举字段,用于标识业务状态)。 【ODS来源】refund_transactions - pay_status。 【JSON字段】refund_transactions.json - $ - pay_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.action_type IS '【说明】明细字段,用于记录事实取值。 【示例】2(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - action_type。 【JSON字段】refund_transactions.json - $ - action_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.is_revoke IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】refund_transactions - is_revoke。 【JSON字段】refund_transactions.json - $ - is_revoke。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.is_delete IS '【说明】布尔/开关字段,用于表示是否/可用性等业务开关。 【示例】0(布尔/开关字段,用于表示是否/可用性等业务开关)。 【ODS来源】refund_transactions - is_delete。 【JSON字段】refund_transactions.json - $ - is_delete。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.check_status IS '【说明】状态枚举字段,用于标识业务状态。 【示例】1(状态枚举字段,用于标识业务状态)。 【ODS来源】refund_transactions - check_status。 【JSON字段】refund_transactions.json - $ - check_status。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.online_pay_channel IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - online_pay_channel。 【JSON字段】refund_transactions.json - $ - online_pay_channel。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.online_pay_type IS '【说明】明细字段,用于记录事实取值。 【示例】0(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - online_pay_type。 【JSON字段】refund_transactions.json - $ - online_pay_type。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_terminal IS '【说明】明细字段,用于记录事实取值。 【示例】1(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - pay_terminal。 【JSON字段】refund_transactions.json - $ - pay_terminal。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.pay_config_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - pay_config_id。 【JSON字段】refund_transactions.json - $ - pay_config_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.cashier_point_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - cashier_point_id。 【JSON字段】refund_transactions.json - $ - cashier_point_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.operator_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】0(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - operator_id。 【JSON字段】refund_transactions.json - $ - operator_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.channel_payer_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】NULL(标识类 ID 字段,用于关联/定位相关实体)。 【ODS来源】refund_transactions - channel_payer_id。 【JSON字段】refund_transactions.json - $ - channel_payer_id。';
+COMMENT ON COLUMN billiards_dwd.dwd_refund_ex.channel_pay_no IS '【说明】明细字段,用于记录事实取值。 【示例】NULL(明细字段,用于记录事实取值)。 【ODS来源】refund_transactions - channel_pay_no。 【JSON字段】refund_transactions.json - $ - channel_pay_no。';
+
+
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/schema_dws.sql b/etl_billiards/dist/ETL_Manager/_internal/database/schema_dws.sql
new file mode 100644
index 0000000..03e1a86
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/schema_dws.sql
@@ -0,0 +1,50 @@
+-- DWS schema for aggregated / serving tables.
+CREATE SCHEMA IF NOT EXISTS billiards_dws;
+
+CREATE TABLE IF NOT EXISTS billiards_dws.dws_order_summary (
+ site_id BIGINT NOT NULL,
+ order_settle_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_date DATE,
+ tenant_id BIGINT,
+ member_id BIGINT,
+ member_flag BOOLEAN,
+ recharge_order_flag BOOLEAN,
+ item_count INT,
+ total_item_quantity NUMERIC,
+ table_fee_amount NUMERIC,
+ assistant_service_amount NUMERIC,
+ goods_amount NUMERIC,
+ group_amount NUMERIC,
+ total_coupon_deduction NUMERIC,
+ member_discount_amount NUMERIC,
+ manual_discount_amount NUMERIC,
+ order_original_amount NUMERIC,
+ order_final_amount NUMERIC,
+ stored_card_deduct NUMERIC,
+ external_paid_amount NUMERIC,
+ total_paid_amount NUMERIC,
+ book_table_flow NUMERIC,
+ book_assistant_flow NUMERIC,
+ book_goods_flow NUMERIC,
+ book_group_flow NUMERIC,
+ book_order_flow NUMERIC,
+ order_effective_consume_cash NUMERIC,
+ order_effective_recharge_cash NUMERIC,
+ order_effective_flow NUMERIC,
+ refund_amount NUMERIC,
+ net_income NUMERIC,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, order_settle_id)
+);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_order_date
+ ON billiards_dws.dws_order_summary (order_date);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_tenant_date
+ ON billiards_dws.dws_order_summary (tenant_id, order_date);
+
+CREATE INDEX IF NOT EXISTS idx_dws_order_summary_member_date
+ ON billiards_dws.dws_order_summary (member_id, order_date);
+
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/schema_etl_admin.sql b/etl_billiards/dist/ETL_Manager/_internal/database/schema_etl_admin.sql
new file mode 100644
index 0000000..de98d86
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/schema_etl_admin.sql
@@ -0,0 +1,105 @@
+-- 文件说明:etl_admin 调度元数据 DDL(独立文件,便于初始化任务单独执行)。
+-- 包含任务注册表、游标表、运行记录表;字段注释使用中文。
+
+CREATE SCHEMA IF NOT EXISTS etl_admin;
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_task (
+ task_id BIGSERIAL PRIMARY KEY,
+ task_code TEXT NOT NULL,
+ store_id BIGINT NOT NULL,
+ enabled BOOLEAN DEFAULT TRUE,
+ cursor_field TEXT,
+ window_minutes_default INT DEFAULT 30,
+ overlap_seconds INT DEFAULT 120,
+ page_size INT DEFAULT 200,
+ retry_max INT DEFAULT 3,
+ params JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_code, store_id)
+);
+COMMENT ON TABLE etl_admin.etl_task IS '任务注册表:调度依据的任务清单(与 task_registry 中的任务码对应)。';
+COMMENT ON COLUMN etl_admin.etl_task.task_code IS '任务编码,需与代码中的任务码一致。';
+COMMENT ON COLUMN etl_admin.etl_task.store_id IS '门店/租户粒度,区分多门店执行。';
+COMMENT ON COLUMN etl_admin.etl_task.enabled IS '是否启用此任务。';
+COMMENT ON COLUMN etl_admin.etl_task.cursor_field IS '增量游标字段名(可选)。';
+COMMENT ON COLUMN etl_admin.etl_task.window_minutes_default IS '默认时间窗口(分钟)。';
+COMMENT ON COLUMN etl_admin.etl_task.overlap_seconds IS '窗口重叠秒数,用于防止遗漏。';
+COMMENT ON COLUMN etl_admin.etl_task.page_size IS '默认分页大小。';
+COMMENT ON COLUMN etl_admin.etl_task.retry_max IS 'API重试次数上限。';
+COMMENT ON COLUMN etl_admin.etl_task.params IS '任务级自定义参数 JSON。';
+COMMENT ON COLUMN etl_admin.etl_task.created_at IS '创建时间。';
+COMMENT ON COLUMN etl_admin.etl_task.updated_at IS '更新时间。';
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_cursor (
+ cursor_id BIGSERIAL PRIMARY KEY,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ last_start TIMESTAMPTZ,
+ last_end TIMESTAMPTZ,
+ last_id BIGINT,
+ last_run_id BIGINT,
+ extra JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_id, store_id)
+);
+COMMENT ON TABLE etl_admin.etl_cursor IS '任务游标表:记录每个任务/门店的增量窗口及最后 run。';
+COMMENT ON COLUMN etl_admin.etl_cursor.task_id IS '关联 etl_task.task_id。';
+COMMENT ON COLUMN etl_admin.etl_cursor.store_id IS '门店/租户粒度。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_start IS '上次窗口开始时间(含重叠偏移)。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_end IS '上次窗口结束时间。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_id IS '上次处理的最大主键/游标值(可选)。';
+COMMENT ON COLUMN etl_admin.etl_cursor.last_run_id IS '上次运行ID,对应 etl_run.run_id。';
+COMMENT ON COLUMN etl_admin.etl_cursor.extra IS '附加游标信息 JSON。';
+COMMENT ON COLUMN etl_admin.etl_cursor.created_at IS '创建时间。';
+COMMENT ON COLUMN etl_admin.etl_cursor.updated_at IS '更新时间。';
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_run (
+ run_id BIGSERIAL PRIMARY KEY,
+ run_uuid TEXT NOT NULL,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ status TEXT NOT NULL,
+ started_at TIMESTAMPTZ DEFAULT now(),
+ ended_at TIMESTAMPTZ,
+ window_start TIMESTAMPTZ,
+ window_end TIMESTAMPTZ,
+ window_minutes INT,
+ overlap_seconds INT,
+ fetched_count INT DEFAULT 0,
+ loaded_count INT DEFAULT 0,
+ updated_count INT DEFAULT 0,
+ skipped_count INT DEFAULT 0,
+ error_count INT DEFAULT 0,
+ unknown_fields INT DEFAULT 0,
+ export_dir TEXT,
+ log_path TEXT,
+ request_params JSONB DEFAULT '{}'::jsonb,
+ manifest JSONB DEFAULT '{}'::jsonb,
+ error_message TEXT,
+ extra JSONB DEFAULT '{}'::jsonb
+);
+COMMENT ON TABLE etl_admin.etl_run IS '运行记录表:记录每次任务执行的窗口、状态、计数与日志路径。';
+COMMENT ON COLUMN etl_admin.etl_run.run_uuid IS '本次调度的唯一标识。';
+COMMENT ON COLUMN etl_admin.etl_run.task_id IS '关联 etl_task.task_id。';
+COMMENT ON COLUMN etl_admin.etl_run.store_id IS '门店/租户粒度。';
+COMMENT ON COLUMN etl_admin.etl_run.status IS '运行状态(SUCC/FAIL/PARTIAL 等)。';
+COMMENT ON COLUMN etl_admin.etl_run.started_at IS '开始时间。';
+COMMENT ON COLUMN etl_admin.etl_run.ended_at IS '结束时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_start IS '本次窗口开始时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_end IS '本次窗口结束时间。';
+COMMENT ON COLUMN etl_admin.etl_run.window_minutes IS '窗口跨度(分钟)。';
+COMMENT ON COLUMN etl_admin.etl_run.overlap_seconds IS '窗口重叠秒数。';
+COMMENT ON COLUMN etl_admin.etl_run.fetched_count IS '抓取/读取的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.loaded_count IS '插入的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.updated_count IS '更新的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.skipped_count IS '跳过的记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.error_count IS '错误记录数。';
+COMMENT ON COLUMN etl_admin.etl_run.unknown_fields IS '未知字段计数(清洗阶段)。';
+COMMENT ON COLUMN etl_admin.etl_run.export_dir IS '抓取/导出目录。';
+COMMENT ON COLUMN etl_admin.etl_run.log_path IS '日志路径。';
+COMMENT ON COLUMN etl_admin.etl_run.request_params IS '请求参数 JSON。';
+COMMENT ON COLUMN etl_admin.etl_run.manifest IS '运行产出清单/统计 JSON。';
+COMMENT ON COLUMN etl_admin.etl_run.error_message IS '错误信息(若失败)。';
+COMMENT ON COLUMN etl_admin.etl_run.extra IS '附加字段,保留扩展。';
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/seed_ods_tasks.sql b/etl_billiards/dist/ETL_Manager/_internal/database/seed_ods_tasks.sql
new file mode 100644
index 0000000..c0184d6
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/seed_ods_tasks.sql
@@ -0,0 +1,41 @@
+-- 将新的 ODS 任务注册到 etl_admin.etl_task(按需替换 store_id)。
+-- 使用方式(示例):
+-- psql "$PG_DSN" -f etl_billiards/database/seed_ods_tasks.sql
+-- 或在 psql 中直接执行本文件内容。
+
+WITH target_store AS (
+ SELECT 2790685415443269::bigint AS store_id -- TODO: 替换为实际 store_id
+),
+task_codes AS (
+ SELECT unnest(ARRAY[
+ -- Must match tasks/ods_tasks.py (ENABLED_ODS_CODES)
+ 'ODS_ASSISTANT_ACCOUNT',
+ 'ODS_ASSISTANT_LEDGER',
+ 'ODS_ASSISTANT_ABOLISH',
+ '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',
+ 'ODS_SETTLEMENT_TICKET'
+ ]) AS task_code
+)
+INSERT INTO etl_admin.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;
diff --git a/etl_billiards/dist/ETL_Manager/_internal/database/seed_scheduler_tasks.sql b/etl_billiards/dist/ETL_Manager/_internal/database/seed_scheduler_tasks.sql
new file mode 100644
index 0000000..2c62a61
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/database/seed_scheduler_tasks.sql
@@ -0,0 +1,50 @@
+-- Seed scheduler-compatible tasks into etl_admin.etl_task.
+--
+-- Notes:
+-- - These task_code values must match orchestration/task_registry.py.
+-- - ODS_* tasks are intentionally excluded here because they don't follow the
+-- BaseTask(cursor_data) scheduler interface in this repo version.
+--
+-- Usage (example):
+-- psql "%PG_DSN%" -f etl_billiards/database/seed_scheduler_tasks.sql
+--
+WITH target_store AS (
+ SELECT 2790685415443269::bigint AS store_id -- TODO: replace with your store_id
+),
+task_codes AS (
+ SELECT unnest(ARRAY[
+ 'ASSISTANT_ABOLISH',
+ 'ASSISTANTS',
+ 'COUPON_USAGE',
+ 'CHECK_CUTOFF',
+ 'DATA_INTEGRITY_CHECK',
+ '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'
+ ]) AS task_code
+)
+INSERT INTO etl_admin.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();
diff --git a/etl_billiards/dist/ETL_Manager/_internal/ffi.dll b/etl_billiards/dist/ETL_Manager/_internal/ffi.dll
new file mode 100644
index 0000000..d57f88f
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/ffi.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/gssapi64.dll b/etl_billiards/dist/ETL_Manager/_internal/gssapi64.dll
new file mode 100644
index 0000000..9b96e3a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/gssapi64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/gui/resources/__init__.py b/etl_billiards/dist/ETL_Manager/_internal/gui/resources/__init__.py
new file mode 100644
index 0000000..ef67034
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/gui/resources/__init__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+"""GUI 资源模块"""
+
+from pathlib import Path
+
+RESOURCES_DIR = Path(__file__).parent
+STYLES_PATH = RESOURCES_DIR / "styles.qss"
+
+
+def load_stylesheet() -> str:
+ """加载样式表"""
+ if STYLES_PATH.exists():
+ return STYLES_PATH.read_text(encoding="utf-8")
+ return ""
diff --git a/etl_billiards/dist/ETL_Manager/_internal/gui/resources/styles.qss b/etl_billiards/dist/ETL_Manager/_internal/gui/resources/styles.qss
new file mode 100644
index 0000000..84457dc
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/gui/resources/styles.qss
@@ -0,0 +1,458 @@
+/* ETL GUI 现代浅色主题样式表 */
+
+/* ========== 全局样式 ========== */
+QWidget {
+ font-family: "Microsoft YaHei", "Segoe UI", sans-serif;
+ font-size: 13px;
+ color: #333333;
+ background-color: #f5f5f5;
+}
+
+QMainWindow {
+ background-color: #f5f5f5;
+}
+
+/* ========== 菜单栏 ========== */
+QMenuBar {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e0e0e0;
+ padding: 4px;
+}
+
+QMenuBar::item {
+ padding: 6px 12px;
+ background-color: transparent;
+ border-radius: 4px;
+}
+
+QMenuBar::item:selected {
+ background-color: #e8f0fe;
+}
+
+QMenu {
+ background-color: #ffffff;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ padding: 4px;
+}
+
+QMenu::item {
+ padding: 8px 24px;
+ border-radius: 4px;
+}
+
+QMenu::item:selected {
+ background-color: #e8f0fe;
+}
+
+/* ========== 工具栏 ========== */
+QToolBar {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e0e0e0;
+ padding: 4px;
+ spacing: 4px;
+}
+
+QToolButton {
+ background-color: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 8px;
+}
+
+QToolButton:hover {
+ background-color: #e8f0fe;
+}
+
+QToolButton:pressed {
+ background-color: #d2e3fc;
+}
+
+/* ========== 按钮 ========== */
+QPushButton {
+ background-color: #1a73e8;
+ color: white;
+ border: none;
+ border-radius: 6px;
+ padding: 8px 16px;
+ font-weight: 500;
+}
+
+QPushButton:hover {
+ background-color: #1557b0;
+}
+
+QPushButton:pressed {
+ background-color: #104080;
+}
+
+QPushButton:disabled {
+ background-color: #dadce0;
+ color: #9aa0a6;
+}
+
+QPushButton[secondary="true"] {
+ background-color: #ffffff;
+ color: #1a73e8;
+ border: 1px solid #dadce0;
+}
+
+QPushButton[secondary="true"]:hover {
+ background-color: #f8f9fa;
+ border-color: #1a73e8;
+}
+
+QPushButton[danger="true"] {
+ background-color: #ea4335;
+}
+
+QPushButton[danger="true"]:hover {
+ background-color: #c5221f;
+}
+
+/* ========== 输入框 ========== */
+QLineEdit, QTextEdit, QPlainTextEdit {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 6px;
+ padding: 8px 12px;
+ selection-background-color: #d2e3fc;
+}
+
+QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
+ border-color: #1a73e8;
+ border-width: 2px;
+ padding: 7px 11px;
+}
+
+QLineEdit:disabled, QTextEdit:disabled, QPlainTextEdit:disabled {
+ background-color: #f1f3f4;
+ color: #9aa0a6;
+}
+
+/* ========== 下拉框 ========== */
+QComboBox {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 6px;
+ padding: 8px 12px;
+ padding-right: 30px;
+}
+
+QComboBox:hover {
+ border-color: #1a73e8;
+}
+
+QComboBox:focus {
+ border-color: #1a73e8;
+ border-width: 2px;
+}
+
+QComboBox::drop-down {
+ border: none;
+ width: 24px;
+}
+
+QComboBox::down-arrow {
+ image: none;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 6px solid #5f6368;
+ margin-right: 8px;
+}
+
+QComboBox QAbstractItemView {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ selection-background-color: #e8f0fe;
+}
+
+/* ========== 复选框 ========== */
+QCheckBox {
+ spacing: 8px;
+}
+
+QCheckBox::indicator {
+ width: 18px;
+ height: 18px;
+ border-radius: 4px;
+ border: 2px solid #5f6368;
+}
+
+QCheckBox::indicator:checked {
+ background-color: #1a73e8;
+ border-color: #1a73e8;
+}
+
+QCheckBox::indicator:hover {
+ border-color: #1a73e8;
+}
+
+/* ========== 列表和树 ========== */
+QListWidget, QTreeWidget, QTableWidget {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ outline: none;
+}
+
+QListWidget::item, QTreeWidget::item {
+ padding: 8px;
+ border-radius: 4px;
+}
+
+QListWidget::item:selected, QTreeWidget::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+}
+
+QListWidget::item:hover, QTreeWidget::item:hover {
+ background-color: #f8f9fa;
+}
+
+QHeaderView::section {
+ background-color: #f8f9fa;
+ border: none;
+ border-bottom: 1px solid #dadce0;
+ padding: 10px 16px;
+ font-weight: 600;
+}
+
+QTableWidget {
+ gridline-color: #e8eaed;
+}
+
+QTableWidget::item {
+ padding: 8px;
+}
+
+QTableWidget::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+}
+
+/* ========== 滚动条 ========== */
+QScrollBar:vertical {
+ background-color: transparent;
+ width: 12px;
+ margin: 0;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #dadce0;
+ border-radius: 6px;
+ min-height: 30px;
+ margin: 2px;
+}
+
+QScrollBar::handle:vertical:hover {
+ background-color: #bdc1c6;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
+ height: 0;
+}
+
+QScrollBar:horizontal {
+ background-color: transparent;
+ height: 12px;
+ margin: 0;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #dadce0;
+ border-radius: 6px;
+ min-width: 30px;
+ margin: 2px;
+}
+
+QScrollBar::handle:horizontal:hover {
+ background-color: #bdc1c6;
+}
+
+QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
+ width: 0;
+}
+
+/* ========== 选项卡 ========== */
+QTabWidget::pane {
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ background-color: #ffffff;
+ margin-top: -1px;
+}
+
+QTabBar::tab {
+ background-color: transparent;
+ border: none;
+ padding: 10px 20px;
+ margin-right: 4px;
+ color: #5f6368;
+}
+
+QTabBar::tab:selected {
+ color: #1a73e8;
+ border-bottom: 2px solid #1a73e8;
+}
+
+QTabBar::tab:hover:!selected {
+ background-color: #f8f9fa;
+ border-radius: 6px 6px 0 0;
+}
+
+/* ========== 分组框 ========== */
+QGroupBox {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ margin-top: 16px;
+ padding: 16px;
+ padding-top: 24px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ left: 16px;
+ padding: 0 8px;
+ background-color: #ffffff;
+ color: #5f6368;
+ font-weight: 600;
+}
+
+/* ========== 进度条 ========== */
+QProgressBar {
+ background-color: #e8eaed;
+ border: none;
+ border-radius: 4px;
+ height: 8px;
+ text-align: center;
+}
+
+QProgressBar::chunk {
+ background-color: #1a73e8;
+ border-radius: 4px;
+}
+
+/* ========== 分割器 ========== */
+QSplitter::handle {
+ background-color: #e0e0e0;
+}
+
+QSplitter::handle:horizontal {
+ width: 2px;
+}
+
+QSplitter::handle:vertical {
+ height: 2px;
+}
+
+QSplitter::handle:hover {
+ background-color: #1a73e8;
+}
+
+/* ========== 状态栏 ========== */
+QStatusBar {
+ background-color: #ffffff;
+ border-top: 1px solid #e0e0e0;
+ padding: 4px;
+}
+
+QStatusBar::item {
+ border: none;
+}
+
+/* ========== 提示框 ========== */
+QToolTip {
+ background-color: #3c4043;
+ color: #ffffff;
+ border: none;
+ border-radius: 4px;
+ padding: 8px 12px;
+}
+
+/* ========== 消息框 ========== */
+QMessageBox {
+ background-color: #ffffff;
+}
+
+/* ========== 导航侧边栏 ========== */
+QListWidget#navList {
+ background-color: #ffffff;
+ border: none;
+ border-right: 1px solid #e0e0e0;
+ padding: 8px;
+}
+
+QListWidget#navList::item {
+ padding: 12px 16px;
+ border-radius: 8px;
+ margin: 2px 0;
+}
+
+QListWidget#navList::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+ font-weight: 600;
+}
+
+/* ========== 日志查看器 ========== */
+QPlainTextEdit#logViewer {
+ font-family: "Consolas", "Courier New", monospace;
+ font-size: 12px;
+ background-color: #fafafa;
+ line-height: 1.5;
+}
+
+/* ========== SQL 编辑器 ========== */
+QPlainTextEdit#sqlEditor {
+ font-family: "Consolas", "Courier New", monospace;
+ font-size: 13px;
+ background-color: #ffffff;
+}
+
+/* ========== 卡片样式 ========== */
+QFrame[card="true"] {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 12px;
+ padding: 16px;
+}
+
+QFrame[card="true"]:hover {
+ border-color: #1a73e8;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* ========== 标签 ========== */
+QLabel[heading="true"] {
+ font-size: 18px;
+ font-weight: 600;
+ color: #202124;
+}
+
+QLabel[subheading="true"] {
+ font-size: 14px;
+ color: #5f6368;
+}
+
+QLabel[status="success"] {
+ color: #1e8e3e;
+ font-weight: 500;
+}
+
+QLabel[status="error"] {
+ color: #d93025;
+ font-weight: 500;
+}
+
+QLabel[status="warning"] {
+ color: #f9ab00;
+ font-weight: 500;
+}
+
+QLabel[status="info"] {
+ color: #1a73e8;
+ font-weight: 500;
+}
diff --git a/etl_billiards/dist/ETL_Manager/_internal/k5sprt64.dll b/etl_billiards/dist/ETL_Manager/_internal/k5sprt64.dll
new file mode 100644
index 0000000..14c6c69
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/k5sprt64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/krb5_64.dll b/etl_billiards/dist/ETL_Manager/_internal/krb5_64.dll
new file mode 100644
index 0000000..9e2b43c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/krb5_64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/libcrypto-3-x64.dll b/etl_billiards/dist/ETL_Manager/_internal/libcrypto-3-x64.dll
new file mode 100644
index 0000000..440c1bc
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/libcrypto-3-x64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/liblzma.dll b/etl_billiards/dist/ETL_Manager/_internal/liblzma.dll
new file mode 100644
index 0000000..da96c30
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/liblzma.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/libmpdec-4.dll b/etl_billiards/dist/ETL_Manager/_internal/libmpdec-4.dll
new file mode 100644
index 0000000..7447f2a
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/libmpdec-4.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/libpq.dll b/etl_billiards/dist/ETL_Manager/_internal/libpq.dll
new file mode 100644
index 0000000..d2a0958
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/libpq.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/libssl-3-x64.dll b/etl_billiards/dist/ETL_Manager/_internal/libssl-3-x64.dll
new file mode 100644
index 0000000..8d4217c
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/libssl-3-x64.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/python3.dll b/etl_billiards/dist/ETL_Manager/_internal/python3.dll
new file mode 100644
index 0000000..7db0269
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/python3.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/python313.dll b/etl_billiards/dist/ETL_Manager/_internal/python313.dll
new file mode 100644
index 0000000..46c52b9
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/python313.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/scheduled_tasks.json b/etl_billiards/dist/ETL_Manager/_internal/scheduled_tasks.json
new file mode 100644
index 0000000..08f7921
--- /dev/null
+++ b/etl_billiards/dist/ETL_Manager/_internal/scheduled_tasks.json
@@ -0,0 +1,48 @@
+{
+ "tasks": {
+ "8e41eb3a": {
+ "id": "8e41eb3a",
+ "name": "数据校验 (最近 2h)",
+ "task_codes": [
+ "DATA_INTEGRITY_CHECK"
+ ],
+ "schedule": {
+ "schedule_type": "interval",
+ "interval_value": 1,
+ "interval_unit": "hours",
+ "daily_time": "04:00",
+ "weekly_days": [
+ 1
+ ],
+ "weekly_time": "04:00",
+ "cron_expression": "0 4 * * *",
+ "enabled": true,
+ "start_date": null,
+ "end_date": null
+ },
+ "task_config": {
+ "pipeline_flow": "FULL",
+ "lookback_hours": 2
+ },
+ "enabled": true,
+ "last_run": "2026-01-27T22:13:11.204212",
+ "next_run": "2026-01-27T23:13:11.204212",
+ "run_count": 1,
+ "last_status": "成功",
+ "execution_history": [
+ {
+ "task_id": "0c577148",
+ "executed_at": "2026-01-27T22:13:11.204212",
+ "status": "success",
+ "exit_code": 0,
+ "duration_seconds": 378.080146,
+ "summary": "【数据校验】检查 107799 条记录, 发现 133 条缺失, 已补全 114 条\n 缺失: ODS_SETTLEMENT_RECORDS: 缺失8/37; ODS_TABLE_USE: 缺失7/10020; ODS_PAYMENT: 缺失8/11849 等12项\n【错误】2026-01-27 22:19:29 [INFO] etl_billiards: 数据补全完成 总缺失=150 已补全=114 错误数=0; 2026-01-27 22:19:29 [INFO] etl_billiards: 自动补全完成 已补全=114 错误数=0\n【结果】✓ etl_billiards: DATA_INTEGRITY_CHECK: 工具类任务执行成功 | ✓ etl_billiards: ETL运行完成",
+ "output": "[工作目录] C:\\dev\\LLTQ\\ETL\\feiqiu-ETL\\etl_billiards\n[执行命令] python -m cli.main --tasks DATA_INTEGRITY_CHECK --pipeline-flow FULL --window-start 2026-01-27 20:13:11 --window-end 2026-01-27 22:13:11\n2026-01-27 22:13:11 [INFO] etl_billiards: 配置加载完成\n2026-01-27 22:13:11 [INFO] etl_billiards: 门店ID: 2790685415443269\n2026-01-27 22:13:11 [INFO] etl_billiards: 任务列表: ['DATA_INTEGRITY_CHECK']\n2026-01-27 22:13:12 [INFO] etl_billiards: 开始运行任务: ['DATA_INTEGRITY_CHECK'], run_uuid=7529523bada34ef8806b976f06eadd5c\n2026-01-27 22:13:12 [INFO] etl_billiards: DATA_INTEGRITY_CHECK: 开始执行工具类任务\n2026-01-27 22:13:12 [INFO] etl_billiards: 检测到 CLI 时间窗口参数,自动切换到 window 模式: 2026-01-27 20:13:11 ~ 2026-01-27 22:13:11\n2026-01-27 22:13:12 [INFO] etl_billiards: START range=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 window_days=0 window_hours=6 split_unit=none comp_hours=0 page_size=200 chunk_size=500\n2026-01-27 22:13:12 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_ACCOUNT table=billiards_ods.assistant_accounts_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:12 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_ACCOUNT idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:13:13 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_ACCOUNT idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=69 missing=0 skipped=0\n2026-01-27 22:13:13 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_ACCOUNT missing=0 records=69 errors=0\n2026-01-27 22:13:13 [INFO] etl_billiards: CHECK_START task=ODS_SETTLEMENT_RECORDS table=billiards_ods.settlement_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:13 [INFO] etl_billiards: WINDOW_START task=ODS_SETTLEMENT_RECORDS idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:13:13 [INFO] etl_billiards: WINDOW_DONE task=ODS_SETTLEMENT_RECORDS idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=37 missing=8 skipped=0\n2026-01-27 22:13:13 [INFO] etl_billiards: CHECK_DONE task=ODS_SETTLEMENT_RECORDS missing=8 records=37 errors=0\n2026-01-27 22:13:13 [INFO] etl_billiards: CHECK_START task=ODS_TABLE_USE table=billiards_ods.table_fee_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:13 [INFO] etl_billiards: WINDOW_START task=ODS_TABLE_USE idx=1 window=FULL\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLE_USE idx=1 window=FULL pages=51 records=10020 missing=7 skipped=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLE_USE missing=7 records=10020 errors=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_LEDGER table=billiards_ods.assistant_service_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_LEDGER idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_LEDGER idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=4 missing=0 skipped=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_LEDGER missing=0 records=4 errors=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_ABOLISH table=billiards_ods.assistant_cancellation_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_ABOLISH idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_ABOLISH idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_ABOLISH missing=0 records=0 errors=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_START task=ODS_STORE_GOODS_SALES table=billiards_ods.store_goods_sales_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_START task=ODS_STORE_GOODS_SALES idx=1 window=FULL\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_DONE task=ODS_STORE_GOODS_SALES idx=1 window=FULL pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_DONE task=ODS_STORE_GOODS_SALES missing=0 records=0 errors=0\n2026-01-27 22:13:27 [INFO] etl_billiards: CHECK_START task=ODS_PAYMENT table=billiards_ods.payment_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:27 [INFO] etl_billiards: WINDOW_START task=ODS_PAYMENT idx=1 window=FULL\n2026-01-27 22:13:49 [INFO] etl_billiards: WINDOW_DONE task=ODS_PAYMENT idx=1 window=FULL pages=60 records=11849 missing=8 skipped=0\n2026-01-27 22:13:49 [INFO] etl_billiards: CHECK_DONE task=ODS_PAYMENT missing=8 records=11849 errors=0\n2026-01-27 22:13:49 [INFO] etl_billiards: CHECK_START task=ODS_REFUND table=billiards_ods.refund_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:49 [INFO] etl_billiards: WINDOW_START task=ODS_REFUND idx=1 window=FULL\n2026-01-27 22:13:49 [INFO] etl_billiards: WINDOW_DONE task=ODS_REFUND idx=1 window=FULL pages=1 records=38 missing=0 skipped=0\n2026-01-27 22:13:49 [INFO] etl_billiards: CHECK_DONE task=ODS_REFUND missing=0 records=38 errors=0\n2026-01-27 22:13:49 [INFO] etl_billiards: CHECK_START task=ODS_PLATFORM_COUPON table=billiards_ods.platform_coupon_redemption_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:13:49 [INFO] etl_billiards: WINDOW_START task=ODS_PLATFORM_COUPON idx=1 window=FULL\n2026-01-27 22:14:20 [INFO] etl_billiards: WINDOW_DONE task=ODS_PLATFORM_COUPON idx=1 window=FULL pages=86 records=17083 missing=4 skipped=0\n2026-01-27 22:14:20 [INFO] etl_billiards: CHECK_DONE task=ODS_PLATFORM_COUPON missing=4 records=17083 errors=0\n2026-01-27 22:14:20 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER table=billiards_ods.member_profiles windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:20 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER idx=1 window=FULL\n2026-01-27 22:14:22 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER idx=1 window=FULL pages=3 records=556 missing=0 skipped=0\n2026-01-27 22:14:22 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER missing=0 records=556 errors=0\n2026-01-27 22:14:22 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER_CARD table=billiards_ods.member_stored_value_cards windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:22 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER_CARD idx=1 window=FULL\n2026-01-27 22:14:24 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER_CARD idx=1 window=FULL pages=5 records=945 missing=0 skipped=0\n2026-01-27 22:14:24 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER_CARD missing=0 records=945 errors=0\n2026-01-27 22:14:24 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER_BALANCE table=billiards_ods.member_balance_changes windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:24 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER_BALANCE idx=1 window=FULL\n2026-01-27 22:14:49 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER_BALANCE idx=1 window=FULL pages=13 records=2480 missing=0 skipped=0\n2026-01-27 22:14:49 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER_BALANCE missing=0 records=2480 errors=0\n2026-01-27 22:14:49 [INFO] etl_billiards: CHECK_START task=ODS_RECHARGE_SETTLE table=billiards_ods.recharge_settlements windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:49 [INFO] etl_billiards: WINDOW_START task=ODS_RECHARGE_SETTLE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:14:49 [INFO] etl_billiards: WINDOW_DONE task=ODS_RECHARGE_SETTLE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:14:49 [INFO] etl_billiards: CHECK_DONE task=ODS_RECHARGE_SETTLE missing=0 records=0 errors=0\n2026-01-27 22:14:49 [INFO] etl_billiards: CHECK_START task=ODS_GROUP_PACKAGE table=billiards_ods.group_buy_packages windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:49 [INFO] etl_billiards: WINDOW_START task=ODS_GROUP_PACKAGE idx=1 window=FULL\n2026-01-27 22:14:50 [INFO] etl_billiards: WINDOW_DONE task=ODS_GROUP_PACKAGE idx=1 window=FULL pages=1 records=18 missing=0 skipped=0\n2026-01-27 22:14:50 [INFO] etl_billiards: CHECK_DONE task=ODS_GROUP_PACKAGE missing=0 records=18 errors=0\n2026-01-27 22:14:50 [INFO] etl_billiards: CHECK_START task=ODS_GROUP_BUY_REDEMPTION table=billiards_ods.group_buy_redemption_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:14:50 [INFO] etl_billiards: WINDOW_START task=ODS_GROUP_BUY_REDEMPTION idx=1 window=FULL\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_DONE task=ODS_GROUP_BUY_REDEMPTION idx=1 window=FULL pages=42 records=8224 missing=8 skipped=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_DONE task=ODS_GROUP_BUY_REDEMPTION missing=8 records=8224 errors=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_START task=ODS_INVENTORY_STOCK table=billiards_ods.goods_stock_summary windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_START task=ODS_INVENTORY_STOCK idx=1 window=FULL\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_DONE task=ODS_INVENTORY_STOCK idx=1 window=FULL pages=1 records=171 missing=0 skipped=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_DONE task=ODS_INVENTORY_STOCK missing=0 records=171 errors=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_START task=ODS_INVENTORY_CHANGE table=billiards_ods.goods_stock_movements windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_START task=ODS_INVENTORY_CHANGE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_DONE task=ODS_INVENTORY_CHANGE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=186 missing=98 skipped=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_DONE task=ODS_INVENTORY_CHANGE missing=98 records=186 errors=0\n2026-01-27 22:15:25 [INFO] etl_billiards: CHECK_START task=ODS_TABLES table=billiards_ods.site_tables_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:25 [INFO] etl_billiards: WINDOW_START task=ODS_TABLES idx=1 window=FULL\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLES idx=1 window=FULL pages=1 records=74 missing=0 skipped=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLES missing=0 records=74 errors=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_START task=ODS_GOODS_CATEGORY table=billiards_ods.stock_goods_category_tree windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_START task=ODS_GOODS_CATEGORY idx=1 window=FULL\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_DONE task=ODS_GOODS_CATEGORY idx=1 window=FULL pages=1 records=9 missing=0 skipped=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_DONE task=ODS_GOODS_CATEGORY missing=0 records=9 errors=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_START task=ODS_STORE_GOODS table=billiards_ods.store_goods_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_START task=ODS_STORE_GOODS idx=1 window=FULL\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_DONE task=ODS_STORE_GOODS idx=1 window=FULL pages=1 records=171 missing=0 skipped=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_DONE task=ODS_STORE_GOODS missing=0 records=171 errors=0\n2026-01-27 22:15:26 [INFO] etl_billiards: CHECK_START task=ODS_TABLE_FEE_DISCOUNT table=billiards_ods.table_fee_discount_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:26 [INFO] etl_billiards: WINDOW_START task=ODS_TABLE_FEE_DISCOUNT idx=1 window=FULL\n2026-01-27 22:15:32 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLE_FEE_DISCOUNT idx=1 window=FULL pages=9 records=1748 missing=0 skipped=0\n2026-01-27 22:15:32 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLE_FEE_DISCOUNT missing=0 records=1748 errors=0\n2026-01-27 22:15:32 [INFO] etl_billiards: CHECK_START task=ODS_TENANT_GOODS table=billiards_ods.tenant_goods_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:32 [INFO] etl_billiards: WINDOW_START task=ODS_TENANT_GOODS idx=1 window=FULL\n2026-01-27 22:15:33 [INFO] etl_billiards: WINDOW_DONE task=ODS_TENANT_GOODS idx=1 window=FULL pages=1 records=172 missing=0 skipped=0\n2026-01-27 22:15:33 [INFO] etl_billiards: CHECK_DONE task=ODS_TENANT_GOODS missing=0 records=172 errors=0\n2026-01-27 22:15:33 [INFO] etl_billiards: CHECK_START task=ODS_SETTLEMENT_TICKET table=billiards_ods.settlement_ticket_details windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:33 [INFO] etl_billiards: WINDOW_START task=ODS_SETTLEMENT_TICKET idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:33 [INFO] etl_billiards: WINDOW_DONE task=ODS_SETTLEMENT_TICKET idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=37 missing=0 skipped=37\n2026-01-27 22:15:33 [INFO] etl_billiards: CHECK_DONE task=ODS_SETTLEMENT_TICKET missing=0 records=37 errors=0\n2026-01-27 22:15:42 [INFO] etl_billiards: 自动补全开始 起始=2026-01-27 20:13:11+08:00 结束=2026-01-27 22:13:11+08:00\n2026-01-27 22:15:43 [INFO] etl_billiards: 数据补全开始 起始=2026-01-27T20:13:11+08:00 结束=2026-01-27T22:13:11+08:00\n2026-01-27 22:15:43 [INFO] etl_billiards: 正在执行缺失检查...\n2026-01-27 22:15:43 [INFO] etl_billiards: START range=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 window_days=0 window_hours=2 split_unit=month comp_hours=2 page_size=200 chunk_size=500\n2026-01-27 22:15:43 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_ACCOUNT table=billiards_ods.assistant_accounts_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:43 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_ACCOUNT idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:45 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_ACCOUNT idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=69 missing=0 skipped=0\n2026-01-27 22:15:45 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_ACCOUNT missing=0 records=69 errors=0\n2026-01-27 22:15:45 [INFO] etl_billiards: CHECK_START task=ODS_SETTLEMENT_RECORDS table=billiards_ods.settlement_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:45 [INFO] etl_billiards: WINDOW_START task=ODS_SETTLEMENT_RECORDS idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:45 [INFO] etl_billiards: WINDOW_DONE task=ODS_SETTLEMENT_RECORDS idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=37 missing=8 skipped=0\n2026-01-27 22:15:45 [INFO] etl_billiards: CHECK_DONE task=ODS_SETTLEMENT_RECORDS missing=8 records=37 errors=0\n2026-01-27 22:15:45 [INFO] etl_billiards: CHECK_START task=ODS_TABLE_USE table=billiards_ods.table_fee_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:45 [INFO] etl_billiards: WINDOW_START task=ODS_TABLE_USE idx=1 window=FULL\n2026-01-27 22:15:58 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLE_USE idx=1 window=FULL pages=51 records=10020 missing=7 skipped=0\n2026-01-27 22:15:58 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLE_USE missing=7 records=10020 errors=0\n2026-01-27 22:15:58 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_LEDGER table=billiards_ods.assistant_service_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:58 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_LEDGER idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_LEDGER idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=4 missing=0 skipped=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_LEDGER missing=0 records=4 errors=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_START task=ODS_ASSISTANT_ABOLISH table=billiards_ods.assistant_cancellation_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_START task=ODS_ASSISTANT_ABOLISH idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_DONE task=ODS_ASSISTANT_ABOLISH idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_DONE task=ODS_ASSISTANT_ABOLISH missing=0 records=0 errors=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_START task=ODS_STORE_GOODS_SALES table=billiards_ods.store_goods_sales_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_START task=ODS_STORE_GOODS_SALES idx=1 window=FULL\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_DONE task=ODS_STORE_GOODS_SALES idx=1 window=FULL pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_DONE task=ODS_STORE_GOODS_SALES missing=0 records=0 errors=0\n2026-01-27 22:15:59 [INFO] etl_billiards: CHECK_START task=ODS_PAYMENT table=billiards_ods.payment_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:15:59 [INFO] etl_billiards: WINDOW_START task=ODS_PAYMENT idx=1 window=FULL\n2026-01-27 22:16:20 [INFO] etl_billiards: WINDOW_DONE task=ODS_PAYMENT idx=1 window=FULL pages=60 records=11849 missing=8 skipped=0\n2026-01-27 22:16:20 [INFO] etl_billiards: CHECK_DONE task=ODS_PAYMENT missing=8 records=11849 errors=0\n2026-01-27 22:16:20 [INFO] etl_billiards: CHECK_START task=ODS_REFUND table=billiards_ods.refund_transactions windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:16:20 [INFO] etl_billiards: WINDOW_START task=ODS_REFUND idx=1 window=FULL\n2026-01-27 22:16:20 [INFO] etl_billiards: WINDOW_DONE task=ODS_REFUND idx=1 window=FULL pages=1 records=38 missing=0 skipped=0\n2026-01-27 22:16:20 [INFO] etl_billiards: CHECK_DONE task=ODS_REFUND missing=0 records=38 errors=0\n2026-01-27 22:16:20 [INFO] etl_billiards: CHECK_START task=ODS_PLATFORM_COUPON table=billiards_ods.platform_coupon_redemption_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:16:20 [INFO] etl_billiards: WINDOW_START task=ODS_PLATFORM_COUPON idx=1 window=FULL\n2026-01-27 22:16:52 [INFO] etl_billiards: WINDOW_DONE task=ODS_PLATFORM_COUPON idx=1 window=FULL pages=86 records=17083 missing=4 skipped=0\n2026-01-27 22:16:52 [INFO] etl_billiards: CHECK_DONE task=ODS_PLATFORM_COUPON missing=4 records=17083 errors=0\n2026-01-27 22:16:52 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER table=billiards_ods.member_profiles windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:16:52 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER idx=1 window=FULL\n2026-01-27 22:16:54 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER idx=1 window=FULL pages=3 records=556 missing=0 skipped=0\n2026-01-27 22:16:54 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER missing=0 records=556 errors=0\n2026-01-27 22:16:54 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER_CARD table=billiards_ods.member_stored_value_cards windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:16:54 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER_CARD idx=1 window=FULL\n2026-01-27 22:16:56 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER_CARD idx=1 window=FULL pages=5 records=945 missing=0 skipped=0\n2026-01-27 22:16:56 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER_CARD missing=0 records=945 errors=0\n2026-01-27 22:16:56 [INFO] etl_billiards: CHECK_START task=ODS_MEMBER_BALANCE table=billiards_ods.member_balance_changes windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:16:56 [INFO] etl_billiards: WINDOW_START task=ODS_MEMBER_BALANCE idx=1 window=FULL\n2026-01-27 22:17:21 [INFO] etl_billiards: WINDOW_DONE task=ODS_MEMBER_BALANCE idx=1 window=FULL pages=13 records=2480 missing=0 skipped=0\n2026-01-27 22:17:21 [INFO] etl_billiards: CHECK_DONE task=ODS_MEMBER_BALANCE missing=0 records=2480 errors=0\n2026-01-27 22:17:21 [INFO] etl_billiards: CHECK_START task=ODS_RECHARGE_SETTLE table=billiards_ods.recharge_settlements windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:21 [INFO] etl_billiards: WINDOW_START task=ODS_RECHARGE_SETTLE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:17:22 [INFO] etl_billiards: WINDOW_DONE task=ODS_RECHARGE_SETTLE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=0 missing=0 skipped=0\n2026-01-27 22:17:22 [INFO] etl_billiards: CHECK_DONE task=ODS_RECHARGE_SETTLE missing=0 records=0 errors=0\n2026-01-27 22:17:22 [INFO] etl_billiards: CHECK_START task=ODS_GROUP_PACKAGE table=billiards_ods.group_buy_packages windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:22 [INFO] etl_billiards: WINDOW_START task=ODS_GROUP_PACKAGE idx=1 window=FULL\n2026-01-27 22:17:22 [INFO] etl_billiards: WINDOW_DONE task=ODS_GROUP_PACKAGE idx=1 window=FULL pages=1 records=18 missing=0 skipped=0\n2026-01-27 22:17:22 [INFO] etl_billiards: CHECK_DONE task=ODS_GROUP_PACKAGE missing=0 records=18 errors=0\n2026-01-27 22:17:22 [INFO] etl_billiards: CHECK_START task=ODS_GROUP_BUY_REDEMPTION table=billiards_ods.group_buy_redemption_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:22 [INFO] etl_billiards: WINDOW_START task=ODS_GROUP_BUY_REDEMPTION idx=1 window=FULL\n2026-01-27 22:17:53 [INFO] etl_billiards: WINDOW_DONE task=ODS_GROUP_BUY_REDEMPTION idx=1 window=FULL pages=42 records=8224 missing=8 skipped=0\n2026-01-27 22:17:53 [INFO] etl_billiards: CHECK_DONE task=ODS_GROUP_BUY_REDEMPTION missing=8 records=8224 errors=0\n2026-01-27 22:17:53 [INFO] etl_billiards: CHECK_START task=ODS_INVENTORY_STOCK table=billiards_ods.goods_stock_summary windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:53 [INFO] etl_billiards: WINDOW_START task=ODS_INVENTORY_STOCK idx=1 window=FULL\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_DONE task=ODS_INVENTORY_STOCK idx=1 window=FULL pages=1 records=171 missing=0 skipped=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_DONE task=ODS_INVENTORY_STOCK missing=0 records=171 errors=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_START task=ODS_INVENTORY_CHANGE table=billiards_ods.goods_stock_movements windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_START task=ODS_INVENTORY_CHANGE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_DONE task=ODS_INVENTORY_CHANGE idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=2 records=203 missing=115 skipped=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_DONE task=ODS_INVENTORY_CHANGE missing=115 records=203 errors=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_START task=ODS_TABLES table=billiards_ods.site_tables_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_START task=ODS_TABLES idx=1 window=FULL\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLES idx=1 window=FULL pages=1 records=74 missing=0 skipped=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLES missing=0 records=74 errors=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_START task=ODS_GOODS_CATEGORY table=billiards_ods.stock_goods_category_tree windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_START task=ODS_GOODS_CATEGORY idx=1 window=FULL\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_DONE task=ODS_GOODS_CATEGORY idx=1 window=FULL pages=1 records=9 missing=0 skipped=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_DONE task=ODS_GOODS_CATEGORY missing=0 records=9 errors=0\n2026-01-27 22:17:54 [INFO] etl_billiards: CHECK_START task=ODS_STORE_GOODS table=billiards_ods.store_goods_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:54 [INFO] etl_billiards: WINDOW_START task=ODS_STORE_GOODS idx=1 window=FULL\n2026-01-27 22:17:55 [INFO] etl_billiards: WINDOW_DONE task=ODS_STORE_GOODS idx=1 window=FULL pages=1 records=171 missing=0 skipped=0\n2026-01-27 22:17:55 [INFO] etl_billiards: CHECK_DONE task=ODS_STORE_GOODS missing=0 records=171 errors=0\n2026-01-27 22:17:55 [INFO] etl_billiards: CHECK_START task=ODS_TABLE_FEE_DISCOUNT table=billiards_ods.table_fee_discount_records windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:17:55 [INFO] etl_billiards: WINDOW_START task=ODS_TABLE_FEE_DISCOUNT idx=1 window=FULL\n2026-01-27 22:18:00 [INFO] etl_billiards: WINDOW_DONE task=ODS_TABLE_FEE_DISCOUNT idx=1 window=FULL pages=9 records=1748 missing=0 skipped=0\n2026-01-27 22:18:00 [INFO] etl_billiards: CHECK_DONE task=ODS_TABLE_FEE_DISCOUNT missing=0 records=1748 errors=0\n2026-01-27 22:18:00 [INFO] etl_billiards: CHECK_START task=ODS_TENANT_GOODS table=billiards_ods.tenant_goods_master windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:18:00 [INFO] etl_billiards: WINDOW_START task=ODS_TENANT_GOODS idx=1 window=FULL\n2026-01-27 22:18:00 [INFO] etl_billiards: WINDOW_DONE task=ODS_TENANT_GOODS idx=1 window=FULL pages=1 records=172 missing=0 skipped=0\n2026-01-27 22:18:00 [INFO] etl_billiards: CHECK_DONE task=ODS_TENANT_GOODS missing=0 records=172 errors=0\n2026-01-27 22:18:00 [INFO] etl_billiards: CHECK_START task=ODS_SETTLEMENT_TICKET table=billiards_ods.settlement_ticket_details windows=1 start=2026-01-27T18:13:11+08:00 end=2026-01-28T00:13:11+08:00\n2026-01-27 22:18:00 [INFO] etl_billiards: WINDOW_START task=ODS_SETTLEMENT_TICKET idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00\n2026-01-27 22:18:01 [INFO] etl_billiards: WINDOW_DONE task=ODS_SETTLEMENT_TICKET idx=1 window=2026-01-27T18:13:11+08:00~2026-01-28T00:13:11+08:00 pages=1 records=37 missing=0 skipped=37\n2026-01-27 22:18:01 [INFO] etl_billiards: CHECK_DONE task=ODS_SETTLEMENT_TICKET missing=0 records=37 errors=0\n2026-01-27 22:18:01 [INFO] etl_billiards: 缺失检查完成 总缺失=150\n2026-01-27 22:18:01 [INFO] etl_billiards: 开始补全任务 任务=ODS_SETTLEMENT_RECORDS 缺失=8 样本数=8\n2026-01-27 22:18:01 [INFO] etl_billiards: 开始获取数据 任务=ODS_SETTLEMENT_RECORDS 缺失主键数=8\n2026-01-27 22:18:01 [INFO] etl_billiards: 已插入 任务=ODS_SETTLEMENT_RECORDS 页=1 数量=8\n2026-01-27 22:18:01 [INFO] etl_billiards: 任务补全完成 任务=ODS_SETTLEMENT_RECORDS 已补全=8\n2026-01-27 22:18:01 [INFO] etl_billiards: 开始补全任务 任务=ODS_TABLE_USE 缺失=7 样本数=7\n2026-01-27 22:18:01 [INFO] etl_billiards: 开始获取数据 任务=ODS_TABLE_USE 缺失主键数=7\n2026-01-27 22:18:02 [INFO] etl_billiards: 已插入 任务=ODS_TABLE_USE 页=1 数量=7\n2026-01-27 22:18:14 [INFO] etl_billiards: 任务补全完成 任务=ODS_TABLE_USE 已补全=7\n2026-01-27 22:18:14 [INFO] etl_billiards: 开始补全任务 任务=ODS_PAYMENT 缺失=8 样本数=8\n2026-01-27 22:18:14 [INFO] etl_billiards: 开始获取数据 任务=ODS_PAYMENT 缺失主键数=8\n2026-01-27 22:18:14 [INFO] etl_billiards: 已插入 任务=ODS_PAYMENT 页=1 数量=8\n2026-01-27 22:18:31 [INFO] etl_billiards: 任务补全完成 任务=ODS_PAYMENT 已补全=8\n2026-01-27 22:18:31 [INFO] etl_billiards: 开始补全任务 任务=ODS_PLATFORM_COUPON 缺失=4 样本数=4\n2026-01-27 22:18:31 [INFO] etl_billiards: 开始获取数据 任务=ODS_PLATFORM_COUPON 缺失主键数=4\n2026-01-27 22:18:32 [INFO] etl_billiards: 已插入 任务=ODS_PLATFORM_COUPON 页=1 数量=4\n2026-01-27 22:18:58 [INFO] etl_billiards: 任务补全完成 任务=ODS_PLATFORM_COUPON 已补全=4\n2026-01-27 22:18:58 [INFO] etl_billiards: 开始补全任务 任务=ODS_GROUP_BUY_REDEMPTION 缺失=8 样本数=8\n2026-01-27 22:18:58 [INFO] etl_billiards: 开始获取数据 任务=ODS_GROUP_BUY_REDEMPTION 缺失主键数=8\n2026-01-27 22:18:59 [INFO] etl_billiards: 已插入 任务=ODS_GROUP_BUY_REDEMPTION 页=1 数量=8\n2026-01-27 22:19:28 [INFO] etl_billiards: 任务补全完成 任务=ODS_GROUP_BUY_REDEMPTION 已补全=8\n2026-01-27 22:19:28 [INFO] etl_billiards: 开始补全任务 任务=ODS_INVENTORY_CHANGE 缺失=115 样本数=115\n2026-01-27 22:19:28 [INFO] etl_billiards: 开始获取数据 任务=ODS_INVENTORY_CHANGE 缺失主键数=115\n2026-01-27 22:19:29 [INFO] etl_billiards: 已插入 任务=ODS_INVENTORY_CHANGE 页=1 数量=79\n2026-01-27 22:19:29 [INFO] etl_billiards: 任务补全完成 任务=ODS_INVENTORY_CHANGE 已补全=79\n2026-01-27 22:19:29 [INFO] etl_billiards: 数据补全完成 总缺失=150 已补全=114 错误数=0\n2026-01-27 22:19:29 [INFO] etl_billiards: 自动补全完成 已补全=114 错误数=0\n2026-01-27 22:19:29 [INFO] etl_billiards: DATA_INTEGRITY_CHECK: 工具类任务执行成功\n2026-01-27 22:19:29 [INFO] etl_billiards: DATA_INTEGRITY_CHECK: 结果统计: {'missing': 133, 'errors': 0, 'backfilled': 114}\n2026-01-27 22:19:29 [INFO] etl_billiards: 所有任务执行完成\n2026-01-27 22:19:29 [INFO] etl_billiards: ETL运行完成\n",
+ "error": ""
+ }
+ ],
+ "created_at": "2026-01-27T22:12:39.781369",
+ "updated_at": "2026-01-27T22:19:29.288249"
+ }
+ }
+}
\ No newline at end of file
diff --git a/etl_billiards/dist/ETL_Manager/_internal/shiboken6/MSVCP140.dll b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/MSVCP140.dll
new file mode 100644
index 0000000..e7b55fd
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/MSVCP140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140.dll b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140.dll
new file mode 100644
index 0000000..f51a624
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140_1.dll b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140_1.dll
new file mode 100644
index 0000000..2545fcc
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/VCRUNTIME140_1.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/shiboken6/shiboken6.abi3.dll b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/shiboken6.abi3.dll
new file mode 100644
index 0000000..4df32b6
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/shiboken6/shiboken6.abi3.dll differ
diff --git a/etl_billiards/dist/ETL_Manager/_internal/zlib.dll b/etl_billiards/dist/ETL_Manager/_internal/zlib.dll
new file mode 100644
index 0000000..8b9f303
Binary files /dev/null and b/etl_billiards/dist/ETL_Manager/_internal/zlib.dll differ
diff --git a/etl_billiards/docs/dwd_main_tables_dictionary.md b/etl_billiards/docs/dwd_main_tables_dictionary.md
new file mode 100644
index 0000000..ea88118
--- /dev/null
+++ b/etl_billiards/docs/dwd_main_tables_dictionary.md
@@ -0,0 +1,1250 @@
+# DWD 主表(非 Ex)表格说明书
+
+
+
+- 来源:`etl_billiards/database/schema_dwd_doc.sql`
+
+- 范围:仅包含“主表”(表名不含 `_Ex`/`_EX` 的 `CREATE TABLE`);扩展字段见同名 `_Ex` 表
+
+- 目的:二次数据清洗/建模的字段口径、来源与可连接关系参考
+
+- 关联(推断)列规则:仅按“字段名 = 其他表主键字段名”推断可 join 关系;DWD 未声明外键,需结合业务确认
+
+
+
+## 表清单
+
+
+
+| 表名 | 类型 | 主键 | 表说明 |
+
+|---|---|---|---|
+
+| `dim_assistant` | 维度 | assistant_id | DWD 维度表:dim_assistant。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_goods_category` | 维度 | category_id | DWD 维度表:dim_goods_category。ODS 来源表:billiards_ods.stock_goods_category_tree(对应 JSON:stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_groupbuy_package` | 维度 | groupbuy_package_id | DWD 维度表:dim_groupbuy_package。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_member` | 维度 | member_id | DWD 维度表:dim_member。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_member_card_account` | 维度 | member_card_id | DWD 维度表:dim_member_card_account。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_site` | 维度 | site_id | DWD 维度表:dim_site。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_store_goods` | 维度 | site_goods_id | DWD 维度表:dim_store_goods。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_table` | 维度 | table_id | DWD 维度表:dim_table。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dim_tenant_goods` | 维度 | tenant_goods_id | DWD 维度表:dim_tenant_goods。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_assistant_service_log` | 事实/明细 | assistant_service_id | DWD 明细事实表:dwd_assistant_service_log。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_assistant_trash_event` | 事实/明细 | assistant_trash_event_id | DWD 明细事实表:dwd_assistant_trash_event。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_groupbuy_redemption` | 事实/明细 | redemption_id | DWD 明细事实表:dwd_groupbuy_redemption。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_member_balance_change` | 事实/明细 | balance_change_id | DWD 明细事实表:dwd_member_balance_change。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_payment` | 事实/明细 | payment_id | DWD 明细事实表:dwd_payment。ODS 来源表:billiards_ods.payment_transactions(对应 JSON:payment_transactions.json;分析:payment_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_platform_coupon_redemption` | 事实/明细 | platform_coupon_redemption_id | DWD 明细事实表:dwd_platform_coupon_redemption。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_recharge_order` | 事实/明细 | recharge_order_id | DWD 明细事实表:dwd_recharge_order。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_refund` | 事实/明细 | refund_id | DWD 明细事实表:dwd_refund。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_settlement_head` | 事实/明细 | order_settle_id | DWD 明细事实表:dwd_settlement_head。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_store_goods_sale` | 事实/明细 | store_goods_sale_id | DWD 明细事实表:dwd_store_goods_sale。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_table_fee_adjust` | 事实/明细 | table_fee_adjust_id | DWD 明细事实表:dwd_table_fee_adjust。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+| `dwd_table_fee_log` | 事实/明细 | table_fee_log_id | DWD 明细事实表:dwd_table_fee_log。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。 |
+
+
+
+## `dim_assistant`
+
+
+
+- 表说明:DWD 维度表:dim_assistant。ODS 来源表:billiards_ods.assistant_accounts_master(对应 JSON:assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:assistant_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `assistant_id` | BIGINT | Y | | 助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。;用途:所有与助教相关的事实表(助教流水、助教排班等)都会通过这个 ID 关联到该维表;用于跨表关联与去重。 | assistant_accounts_master - id。 | assistant_accounts_master.json - data.assistantInfos - id。 |
+
+| `user_id` | BIGINT | | | 预留给“人事系统员工 ID”的字段,目前未接入或未启用;用于跨表关联与去重。 | assistant_accounts_master - staff_id。 | assistant_accounts_master.json - data.assistantInfos - staff_id。 |
+
+| `assistant_no` | TEXT | | | 助教工号 / 编号,便于业务侧识别。;关联:在“助教流水.json”中有 assistantNo,与此字段对应。 | assistant_accounts_master - assistant_no。 | assistant_accounts_master.json - data.assistantInfos - assistant_no。 |
+
+| `real_name` | TEXT | | | 助教真实姓名,如“何海婷”“梁婷婷”等。;关联:在“助教流水.json”的 assistantName 与此一致。 | assistant_accounts_master - real_name。 | assistant_accounts_master.json - data.assistantInfos - real_name。 |
+
+| `nickname` | TEXT | | | 助教在前台展示的昵称,如“佳怡”“周周”“球球”等。 | assistant_accounts_master - nickname。 | assistant_accounts_master.json - data.assistantInfos - nickname。 |
+
+| `mobile` | TEXT | | | 助教手机号,用于登录绑定、通知、钉钉同步等。 | assistant_accounts_master - mobile。 | assistant_accounts_master.json - data.assistantInfos - mobile。 |
+
+| `tenant_id` | BIGINT | | | 品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识;用途:多租户数据隔离与按租户汇总。 | assistant_accounts_master - tenant_id。 | assistant_accounts_master.json - data.assistantInfos - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,对应本次数据的这家球房(朗朗桌球)。;关联:与其它 JSON(台费流水、库存、销售等)中的 site_id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | assistant_accounts_master - site_id。 | assistant_accounts_master.json - data.assistantInfos - site_id。 |
+
+| `team_id` | BIGINT | | | 助教所属团队 ID。;关联:在“助教流水.json”中 assistant_team_id 与此一致;用于跨表关联与去重。 | assistant_accounts_master - team_id。 | assistant_accounts_master.json - data.assistantInfos - team_id。 |
+
+| `team_name` | TEXT | | | 团队名称,展示用,和 team_id 一一对应。 | assistant_accounts_master - team_name。 | assistant_accounts_master.json - data.assistantInfos - team_name。 |
+
+| `level` | INTEGER | | | 8:助教管理/管理员(和流水里的 "助教管理" 对应);关联:在“助教流水.json”里以 assistant_level+levelName 体现。 | assistant_accounts_master - level。 | assistant_accounts_master.json - data.assistantInfos - level。 |
+
+| `entry_time` | TIMESTAMPTZ | | | 入职时间。 | assistant_accounts_master - entry_time。 | assistant_accounts_master.json - data.assistantInfos - entry_time。 |
+
+| `resign_time` | TIMESTAMPTZ | | | 离职日期;使用“远未来日期”作为“未离职”的占位。 | assistant_accounts_master - resign_time。 | assistant_accounts_master.json - data.assistantInfos - resign_time。 |
+
+| `leave_status` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | assistant_accounts_master - leave_status。 | assistant_accounts_master.json - data.assistantInfos - leave_status。 |
+
+| `assistant_status` | INTEGER | | | 账号启用状态:。 | assistant_accounts_master - assistant_status。 | assistant_accounts_master.json - data.assistantInfos - assistant_status。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_goods_category`
+
+
+
+- 表说明:DWD 维度表:dim_goods_category。ODS 来源表:billiards_ods.stock_goods_category_tree(对应 JSON:stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:category_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `category_id` | BIGINT | Y | | 分类节点主键 ID(在商品分类维度中的唯一标识);用于跨表关联与去重。 | stock_goods_category_tree - id。 | stock_goods_category_tree.json - data.goodsCategoryList - id。 |
+
+| `tenant_id` | BIGINT | | | 租户 ID(品牌/商户 ID);用途:多租户数据隔离与按租户汇总。 | stock_goods_category_tree - tenant_id。 | stock_goods_category_tree.json - data.goodsCategoryList - tenant_id。 |
+
+| `category_name` | VARCHAR(50) | | | 分类名称(实际业务分类名称)。 | stock_goods_category_tree - category_name。 | stock_goods_category_tree.json - data.goodsCategoryList - category_name。 |
+
+| `alias_name` | VARCHAR(50) | | | 预留的“别名”字段,可用于:。 | stock_goods_category_tree - alias_name。 | stock_goods_category_tree.json - data.goodsCategoryList - alias_name。 |
+
+| `parent_category_id` | BIGINT | | | 父级分类 ID;用于跨表关联与去重。 | stock_goods_category_tree - pid。 | stock_goods_category_tree.json - data.goodsCategoryList - pid。 |
+
+| `business_name` | VARCHAR(50) | | | 业务大类名称。 | stock_goods_category_tree - business_name。 | stock_goods_category_tree.json - data.goodsCategoryList - business_name。 |
+
+| `tenant_goods_business_id` | BIGINT | | | 业务大类 ID;用于跨表关联与去重。 | stock_goods_category_tree - tenant_goods_business_id。 | stock_goods_category_tree.json - data.goodsCategoryList - tenant_goods_business_id。 |
+
+| `category_level` | INTEGER | | | 业务明细字段,用于补充该记录的业务属性。 | stock_goods_category_tree - CASE WHEN pid = 0 THEN 1 ELSE 2 END。 | stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN pid = 0 THEN 1 ELSE 2 END。 |
+
+| `is_leaf` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | stock_goods_category_tree - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。 | stock_goods_category_tree.json - data.goodsCategoryList - CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END。 |
+
+| `open_salesman` | INTEGER | | | 是否启用“营业员”或“导购提成”相关的功能开关。 | stock_goods_category_tree - open_salesman。 | stock_goods_category_tree.json - data.goodsCategoryList - open_salesman。 |
+
+| `sort_order` | INTEGER | | | 分类的排序序号,用于前端展示顺序的控制。 | stock_goods_category_tree - sort。 | stock_goods_category_tree.json - data.goodsCategoryList - sort。 |
+
+| `is_warehousing` | INTEGER | | | 是否“走库存 / 参与仓储管理”:。 | stock_goods_category_tree - is_warehousing。 | stock_goods_category_tree.json - data.goodsCategoryList - is_warehousing。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_groupbuy_package`
+
+
+
+- 表说明:DWD 维度表:dim_groupbuy_package。ODS 来源表:billiards_ods.group_buy_packages(对应 JSON:group_buy_packages.json;分析:group_buy_packages-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:groupbuy_package_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `groupbuy_package_id` | BIGINT | Y | | 门店侧套餐 ID,本文件内部的主键。;关联:平台验券记录表中常见 group_package_id 字段,通常会指向这里的 id,即:平台券核销记录指向哪一个团购套餐配置;用于跨表关联与去重。 | group_buy_packages - id。 | group_buy_packages.json - data.packageCouponList - id。 |
+
+| `tenant_id` | BIGINT | | | 租户 ID(品牌/商户 ID);用途:多租户数据隔离与按租户汇总。 | group_buy_packages - tenant_id。 | group_buy_packages.json - data.packageCouponList - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID;用途:门店维度分组、计营业额、与门店档案关联。 | group_buy_packages - site_id。 | group_buy_packages.json - data.packageCouponList - site_id。 |
+
+| `package_name` | VARCHAR(200) | | | 团购套餐名称,用于前台展示和核销界面。 | group_buy_packages - package_name。 | group_buy_packages.json - data.packageCouponList - package_name。 |
+
+| `package_template_id` | BIGINT | | | “上层套餐 ID” 或“总部/系统级套餐 ID”;用于跨表关联与去重。 | group_buy_packages - package_id。 | group_buy_packages.json - data.packageCouponList - package_id。 |
+
+| `selling_price` | NUMERIC(10,2) | | | 语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。 | group_buy_packages - selling_price。 | group_buy_packages.json - data.packageCouponList - selling_price。 |
+
+| `coupon_face_value` | NUMERIC(10,2) | | | 券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。 | group_buy_packages - coupon_money。 | group_buy_packages.json - data.packageCouponList - coupon_money。 |
+
+| `duration_seconds` | INTEGER | | | 套餐内包含的时长(秒)。 | group_buy_packages - duration。 | group_buy_packages.json - data.packageCouponList - duration。 |
+
+| `start_time` | TIMESTAMPTZ | | | 套餐开始生效的日期时间。 | group_buy_packages - start_time。 | group_buy_packages.json - data.packageCouponList - start_time。 |
+
+| `end_time` | TIMESTAMPTZ | | | 套餐失效的日期时间(到这个时间点后不可使用)。 | group_buy_packages - end_time。 | group_buy_packages.json - data.packageCouponList - end_time。 |
+
+| `table_area_name` | VARCHAR(100) | | | 套餐适用的“门店台区名称”,用于显示和筛选。 | group_buy_packages - table_area_name。 | group_buy_packages.json - data.packageCouponList - table_area_name。 |
+
+| `is_enabled` | INTEGER | | | 启用状态。 | group_buy_packages - is_enabled。 | group_buy_packages.json - data.packageCouponList - is_enabled。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志;软删除/作废标记,分析通常需过滤为有效记录。 | group_buy_packages - is_delete。 | group_buy_packages.json - data.packageCouponList - is_delete。 |
+
+| `create_time` | TIMESTAMPTZ | | | 该套餐在系统中创建的时间;记录源系统创建时间,用于增量同步和口径对齐。 | group_buy_packages - create_time。 | group_buy_packages.json - data.packageCouponList - create_time。 |
+
+| `tenant_table_area_id_list` | VARCHAR(512) | | | 实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。 | group_buy_packages - tenant_table_area_id_list。 | group_buy_packages.json - data.packageCouponList - tenant_table_area_id_list。 |
+
+| `card_type_ids` | VARCHAR(255) | | | 原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。 | group_buy_packages - card_type_ids。 | group_buy_packages.json - data.packageCouponList - card_type_ids。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_member`
+
+
+
+- 表说明:DWD 维度表:dim_member。ODS 来源表:billiards_ods.member_profiles(对应 JSON:member_profiles.json;分析:member_profiles-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:member_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `member_id` | BIGINT | Y | | 这是“租户内会员账户”的主键 ID;用于跨表关联与去重。 | member_profiles - id。 | member_profiles.json - data.tenantMemberInfos - id。 |
+
+| `system_member_id` | BIGINT | | | 这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上;用于跨表关联与去重。 | member_profiles - system_member_id。 | member_profiles.json - data.tenantMemberInfos - system_member_id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID;用途:多租户数据隔离与按租户汇总。 | member_profiles - tenant_id。 | member_profiles.json - data.tenantMemberInfos - tenant_id。 |
+
+| `register_site_id` | BIGINT | | | 会员的注册门店 ID;用于跨表关联与去重。 | member_profiles - register_site_id。 | member_profiles.json - data.tenantMemberInfos - register_site_id。 |
+
+| `mobile` | TEXT | | | 会员绑定的手机号码;手机号码,用于账户/会员识别、查询与联系。 | member_profiles - mobile。 | member_profiles.json - data.tenantMemberInfos - mobile。 |
+
+| `nickname` | TEXT | | | 会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。 | member_profiles - nickname。 | member_profiles.json - data.tenantMemberInfos - nickname。 |
+
+| `member_card_grade_code` | BIGINT | | | 业务明细字段,用于补充该记录的业务属性。 | member_profiles - member_card_grade_code。 | member_profiles.json - data.tenantMemberInfos - member_card_grade_code。 |
+
+| `member_card_grade_name` | TEXT | | | 这是“会员卡种类/等级”的定义字段。 | member_profiles - member_card_grade_name。 | member_profiles.json - data.tenantMemberInfos - member_card_grade_name。 |
+
+| `create_time` | TIMESTAMPTZ | | | 会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间);记录源系统创建时间,用于增量同步和口径对齐。 | member_profiles - create_time。 | member_profiles.json - data.tenantMemberInfos - create_time。 |
+
+| `update_time` | TIMESTAMPTZ | | | 记录源系统更新时间,用于增量同步与变更追踪。 | member_profiles - update_time。 | member_profiles.json - data.tenantMemberInfos - update_time。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_member_card_account`
+
+
+
+- 表说明:DWD 维度表:dim_member_card_account。ODS 来源表:billiards_ods.member_stored_value_cards(对应 JSON:member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:member_card_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `member_card_id` | BIGINT | Y | | 会员卡 ID(源系统唯一标识),用于跨表关联、去重与维度汇总。 | member_stored_value_cards - id。 | member_stored_value_cards.json - data.tenantMemberCards - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID,与其他 JSON 中 tenant_id 一致;用途:多租户数据隔离与按租户汇总。 | member_stored_value_cards - tenant_id。 | member_stored_value_cards.json - data.tenantMemberCards - tenant_id。 |
+
+| `register_site_id` | BIGINT | | | 卡首次办理的门店 ID;用于跨表关联与去重。 | member_stored_value_cards - register_site_id。 | member_stored_value_cards.json - data.tenantMemberCards - register_site_id。 |
+
+| `tenant_member_id` | BIGINT | | | 当前商户(品牌/租户)中会员的主键 ID;用于跨表关联与去重。 | member_stored_value_cards - tenant_member_id。 | member_stored_value_cards.json - data.tenantMemberCards - tenant_member_id。 |
+
+| `system_member_id` | BIGINT | | | 系统级会员 ID(跨门店统一主键);用于跨表关联与去重。 | member_stored_value_cards - system_member_id。 | member_stored_value_cards.json - data.tenantMemberCards - system_member_id。 |
+
+| `card_type_id` | BIGINT | | | 卡种 ID(定义“这是哪一种卡”);用于跨表关联与去重。 | member_stored_value_cards - card_type_id。 | member_stored_value_cards.json - data.tenantMemberCards - card_type_id。 |
+
+| `member_card_grade_code` | BIGINT | | | 卡等级/卡类代码,和下面两个名称字段一一对应。 | member_stored_value_cards - member_card_grade_code。 | member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code。 |
+
+| `member_card_grade_code_name` | TEXT | | | 卡等级/卡类名称。 | member_stored_value_cards - member_card_grade_code_name。 | member_stored_value_cards.json - data.tenantMemberCards - member_card_grade_code_name。 |
+
+| `member_card_type_name` | TEXT | | | 卡类型名称,实际与 member_card_grade_code_name 一致。 | member_stored_value_cards - member_card_type_name。 | member_stored_value_cards.json - data.tenantMemberCards - member_card_type_name。 |
+
+| `member_name` | TEXT | | | 持卡会员姓名快照。 | member_stored_value_cards - member_name。 | member_stored_value_cards.json - data.tenantMemberCards - member_name。 |
+
+| `member_mobile` | TEXT | | | 持卡会员手机号快照;手机号码,用于账户/会员识别、查询与联系。 | member_stored_value_cards - member_mobile。 | member_stored_value_cards.json - data.tenantMemberCards - member_mobile。 |
+
+| `balance` | NUMERIC(18,2) | | | 当前卡内余额(主要针对储值卡、部分券卡)。 | member_stored_value_cards - balance。 | member_stored_value_cards.json - data.tenantMemberCards - balance。 |
+
+| `start_time` | TIMESTAMPTZ | | | 卡片生效开始时间(有效期起始)。 | member_stored_value_cards - start_time。 | member_stored_value_cards.json - data.tenantMemberCards - start_time。 |
+
+| `end_time` | TIMESTAMPTZ | | | 卡片有效期结束时间。 | member_stored_value_cards - end_time。 | member_stored_value_cards.json - data.tenantMemberCards - end_time。 |
+
+| `last_consume_time` | TIMESTAMPTZ | | | 最近一次消费时间。 | member_stored_value_cards - last_consume_time。 | member_stored_value_cards.json - data.tenantMemberCards - last_consume_time。 |
+
+| `status` | INTEGER | | | 1:正常可用。 | member_stored_value_cards - status。 | member_stored_value_cards.json - data.tenantMemberCards - status。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志;软删除/作废标记,分析通常需过滤为有效记录。 | member_stored_value_cards - is_delete。 | member_stored_value_cards.json - data.tenantMemberCards - is_delete。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_site`
+
+
+
+- 表说明:DWD 维度表:dim_site。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:site_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `site_id` | BIGINT | Y | | 门店 ID,本次数据全部来自同一门店(朗朗桌球)。;关联:与 siteProfile.id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | table_fee_transactions - site_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - site_id。 |
+
+| `org_id` | BIGINT | | | 组织/机构 ID,用于组织维度归属和管理聚合。 | table_fee_transactions - siteProfile.org_id。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - org_id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID。本文件所有记录都属于同一租户。;关联:与所有其它 JSON 中的 tenant_id 一致,用于跨表做“商户维度”的过滤。 | table_fee_transactions - siteProfile.tenant_id。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_id。 |
+
+| `shop_name` | TEXT | | | 名称字段,用于展示、检索与分组。 | table_fee_transactions - siteProfile.shop_name。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_name。 |
+
+| `site_label` | TEXT | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.site_label。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_label。 |
+
+| `full_address` | TEXT | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.full_address。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - full_address。 |
+
+| `address` | TEXT | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.address。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - address。 |
+
+| `longitude` | NUMERIC(10,6) | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.longitude。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - longitude(派生:CAST(longitude AS numeric))。 |
+
+| `latitude` | NUMERIC(10,6) | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.latitude。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - latitude(派生:CAST(latitude AS numeric))。 |
+
+| `tenant_site_region_id` | BIGINT | | | 租户/品牌门店区域 ID(源系统唯一标识),用于跨表关联、去重与维度汇总。 | table_fee_transactions - siteProfile.tenant_site_region_id。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - tenant_site_region_id。 |
+
+| `business_tel` | TEXT | | | 业务明细字段,用于补充该记录的业务属性。 | table_fee_transactions - siteProfile.business_tel。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - business_tel。 |
+
+| `site_type` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | table_fee_transactions - siteProfile.site_type。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - site_type。 |
+
+| `shop_status` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | table_fee_transactions - siteProfile.shop_status。 | table_fee_transactions.json - data.siteTableUseDetailsList.siteProfile - shop_status。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_store_goods`
+
+
+
+- 表说明:DWD 维度表:dim_store_goods。ODS 来源表:billiards_ods.store_goods_master(对应 JSON:store_goods_master.json;分析:store_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:site_goods_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `site_goods_id` | BIGINT | Y | | 门店商品 ID,门店维度的商品主键;用于跨表关联与去重。 | store_goods_master - id。 | store_goods_master.json - data.orderGoodsList - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID。同一品牌下多个门店共享一个 tenant_id;用途:多租户数据隔离与按租户汇总。 | store_goods_master - tenant_id。 | store_goods_master.json - data.orderGoodsList - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID;用途:门店维度分组、计营业额、与门店档案关联。 | store_goods_master - site_id。 | store_goods_master.json - data.orderGoodsList - site_id。 |
+
+| `tenant_goods_id` | BIGINT | | dim_tenant_goods(tenant_goods_id) | 租户/品牌维度的商品 ID,相当于“全局商品 ID”;用于跨表关联与去重。 | store_goods_master - tenant_goods_id。 | store_goods_master.json - data.orderGoodsList - tenant_goods_id。 |
+
+| `goods_name` | TEXT | | | 商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。 | store_goods_master - goods_name。 | store_goods_master.json - data.orderGoodsList - goods_name。 |
+
+| `goods_category_id` | BIGINT | | | 商品一级分类 ID;用于跨表关联与去重。 | store_goods_master - goods_category_id。 | store_goods_master.json - data.orderGoodsList - goods_category_id。 |
+
+| `goods_second_category_id` | BIGINT | | | 商品二级分类 ID;用于跨表关联与去重。 | store_goods_master - goods_second_category_id。 | store_goods_master.json - data.orderGoodsList - goods_second_category_id。 |
+
+| `category_level1_name` | TEXT | | | 一级分类名称,如“零食”“酒水”“服务费”等。 | store_goods_master - oneCategoryName。 | store_goods_master.json - data.orderGoodsList - oneCategoryName。 |
+
+| `category_level2_name` | TEXT | | | 二级分类名称,如“面”“洋酒”“纸巾”等。 | store_goods_master - twoCategoryName。 | store_goods_master.json - data.orderGoodsList - twoCategoryName。 |
+
+| `batch_stock_qty` | INTEGER | | | 当前可用库存数量(以 unit 为单位)。 | store_goods_master - stock。 | store_goods_master.json - data.orderGoodsList - stock。 |
+
+| `sale_qty` | INTEGER | | | 在当前统计口径下的销售数量(总销量,单位同 unit)。 | store_goods_master - sale_num。 | store_goods_master.json - data.orderGoodsList - sale_num。 |
+
+| `total_sales_qty` | INTEGER | | | 累计销售数量。 | store_goods_master - total_sales。 | store_goods_master.json - data.orderGoodsList - total_sales。 |
+
+| `sale_price` | NUMERIC(18,2) | | | 商品标准销售价(挂牌价),单位为元。 | store_goods_master - sale_price。 | store_goods_master.json - data.orderGoodsList - sale_price。 |
+
+| `created_at` | TIMESTAMPTZ | | | 门店商品档案创建时间(商品在门店建立档案的时间点)。 | store_goods_master - create_time。 | store_goods_master.json - data.orderGoodsList - create_time。 |
+
+| `updated_at` | TIMESTAMPTZ | | | 最后一次修改该商品档案的时间(包括价格调整、状态变更等)。 | store_goods_master - update_time。 | store_goods_master.json - data.orderGoodsList - update_time。 |
+
+| `avg_monthly_sales` | NUMERIC(18,4) | | | 平均月销量(件/月),根据某个统计周期内的销售数据折算而来。 | store_goods_master - average_monthly_sales。 | store_goods_master.json - data.orderGoodsList - average_monthly_sales。 |
+
+| `goods_state` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | store_goods_master - goods_state。 | store_goods_master.json - data.orderGoodsList - goods_state。 |
+
+| `enable_status` | INTEGER | | | 1:启用。;用途:控制商品档案是否参与任何业务(库存、销售等)。 | store_goods_master - enable_status。 | store_goods_master.json - data.orderGoodsList - enable_status。 |
+
+| `send_state` | INTEGER | | | 1:可销售/可下单。 | store_goods_master - send_state。 | store_goods_master.json - data.orderGoodsList - send_state。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志;软删除/作废标记,分析通常需过滤为有效记录。 | store_goods_master - is_delete。 | store_goods_master.json - data.orderGoodsList - is_delete。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_table`
+
+
+
+- 表说明:DWD 维度表:dim_table。ODS 来源表:billiards_ods.site_tables_master(对应 JSON:site_tables_master.json;分析:site_tables_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:table_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `table_id` | BIGINT | Y | | 台桌主键 ID。;用途:这是“台”的全系统唯一标识,是各类流水表引用的核心外键。;关联:与 台费流水.json 中的 site_table_id 一致;用于跨表关联与去重。 | site_tables_master - id。 | site_tables_master.json - data.siteTables - id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID。;关联:与各个流水表、siteProfile.id 一致,本数据全部属于“朗朗桌球”这一家门店;用途:门店维度分组、计营业额、与门店档案关联。 | site_tables_master - site_id。 | site_tables_master.json - data.siteTables - site_id。 |
+
+| `table_name` | TEXT | | | 台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。 | site_tables_master - table_name。 | site_tables_master.json - data.siteTables - table_name。 |
+
+| `site_table_area_id` | BIGINT | | | 门店维度的“台桌区域 ID”;用于跨表关联与去重。 | site_tables_master - site_table_area_id。 | site_tables_master.json - data.siteTables - site_table_area_id。 |
+
+| `site_table_area_name` | TEXT | | | 区域名称,用于前台展示和区域维度管理。 | site_tables_master - areaName。 | site_tables_master.json - data.siteTables - areaName。 |
+
+| `tenant_table_area_id` | BIGINT | | | 门店维度的“台桌区域 ID”;用于跨表关联与去重。 | site_tables_master - site_table_area_id。 | site_tables_master.json - data.siteTables - site_table_area_id。 |
+
+| `table_price` | NUMERIC(18,2) | | | 设计上应为“台的基础单价”字段(例如按小时或按局单价)。 | site_tables_master - table_price。 | site_tables_master.json - data.siteTables - table_price。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dim_tenant_goods`
+
+
+
+- 表说明:DWD 维度表:dim_tenant_goods。ODS 来源表:billiards_ods.tenant_goods_master(对应 JSON:tenant_goods_master.json;分析:tenant_goods_master-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:tenant_goods_id
+
+- 类型:维度
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `tenant_goods_id` | BIGINT | Y | | 商品档案主键 ID,唯一标识一条商品。;用途:作为其他业务表(销售明细、库存流水、门店商品表等)的外键,通常以 tenant_goods_id 或类似字段出现;用于跨表关联与去重。 | tenant_goods_master - id。 | tenant_goods_master.json - data.tenantGoodsList - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID。;用途:和其它 JSON 中的 tenant_id / tenantId 一致,用于区分不同商户(本次数据只包含同一租户)。 | tenant_goods_master - tenant_id。 | tenant_goods_master.json - data.tenantGoodsList - tenant_id。 |
+
+| `supplier_id` | BIGINT | | | 供应商 ID,用于关联到供应商档案。 | tenant_goods_master - supplier_id。 | tenant_goods_master.json - data.tenantGoodsList - supplier_id。 |
+
+| `category_name` | VARCHAR(64) | | | 商品一级分类名称(业务可读)。 | tenant_goods_master - categoryName。 | tenant_goods_master.json - data.tenantGoodsList - categoryName。 |
+
+| `goods_category_id` | BIGINT | | | 商品一级分类 ID;用于跨表关联与去重。 | tenant_goods_master - goods_category_id。 | tenant_goods_master.json - data.tenantGoodsList - goods_category_id。 |
+
+| `goods_second_category_id` | BIGINT | | | 商品二级分类 ID;用于跨表关联与去重。 | tenant_goods_master - goods_second_category_id。 | tenant_goods_master.json - data.tenantGoodsList - goods_second_category_id。 |
+
+| `goods_name` | VARCHAR(128) | | | 商品名称(前台展示名称)。 | tenant_goods_master - goods_name。 | tenant_goods_master.json - data.tenantGoodsList - goods_name。 |
+
+| `goods_number` | VARCHAR(64) | | | 商品内部编码(自定义货号/系统货号)。 | tenant_goods_master - goods_number。 | tenant_goods_master.json - data.tenantGoodsList - goods_number。 |
+
+| `unit` | VARCHAR(16) | | | 计量单位。 | tenant_goods_master - unit。 | tenant_goods_master.json - data.tenantGoodsList - unit。 |
+
+| `market_price` | NUMERIC(18,2) | | | 商品标价 / 售价(标准销售单价)。 | tenant_goods_master - market_price。 | tenant_goods_master.json - data.tenantGoodsList - market_price。 |
+
+| `goods_state` | INTEGER | | | 商品状态(上架/下架等)。 | tenant_goods_master - goods_state。 | tenant_goods_master.json - data.tenantGoodsList - goods_state。 |
+
+| `create_time` | TIMESTAMPTZ | | | 商品档案创建时间;记录源系统创建时间,用于增量同步和口径对齐。 | tenant_goods_master - create_time。 | tenant_goods_master.json - data.tenantGoodsList - create_time。 |
+
+| `update_time` | TIMESTAMPTZ | | | 商品档案最近一次修改时间;记录源系统更新时间,用于增量同步与变更追踪。 | tenant_goods_master - update_time。 | tenant_goods_master.json - data.tenantGoodsList - update_time。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志;软删除/作废标记,分析通常需过滤为有效记录。 | tenant_goods_master - is_delete。 | tenant_goods_master.json - data.tenantGoodsList - is_delete。 |
+
+| `SCD2_start_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本生效起始时间,用于历史追踪。 | | |
+
+| `SCD2_end_time` | TIMESTAMPTZ | | | 维度慢变(SCD2)版本失效时间(默认 9999-12-31 表示当前版本),用于历史追踪。 | | |
+
+| `SCD2_is_current` | INT | | | 维度慢变(SCD2)当前版本标记(1=当前),用于筛选最新维度记录。 | | |
+
+| `SCD2_version` | INT | | | 维度慢变(SCD2)版本号(自增),用于区分历史版本。 | | |
+
+
+
+## `dwd_assistant_service_log`
+
+
+
+- 表说明:DWD 明细事实表:dwd_assistant_service_log。ODS 来源表:billiards_ods.assistant_service_records(对应 JSON:assistant_service_records.json;分析:assistant_service_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:assistant_service_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `assistant_service_id` | BIGINT | Y | | 本条助教流水记录的主键 ID(流水唯一标识)。;用途:在系统内部唯一定位这一条助教服务记录;用于跨表关联与去重。 | assistant_service_records - id。 | assistant_service_records.json - data.orderAssistantDetails - id。 |
+
+| `order_trade_no` | BIGINT | | | 订单交易号,整个订单层面的编号。;关联:与台费流水、门店销售记录、团购套餐流水等表中的同名字段是一致的,用于把 同一笔订单下的各类消费明细(台费/商品/助教/套餐)串起来。 | assistant_service_records - order_trade_no。 | assistant_service_records.json - data.orderAssistantDetails - order_trade_no。 |
+
+| `order_settle_id` | BIGINT | | dwd_settlement_head(order_settle_id) | 订单结算 ID,相当于“结账单号”的内部主键。;关联:与小票详情中的 orderSettleId 对应;用于跨表关联与去重。 | assistant_service_records - order_settle_id。 | assistant_service_records.json - data.orderAssistantDetails - order_settle_id。 |
+
+| `order_pay_id` | BIGINT | | | 关联到“支付记录”的主键 ID。;用途:可以和支付记录中的 id / relate_id 等字段对应,找到这条助教服务对应的支付流水;用于跨表关联与去重。 | assistant_service_records - order_pay_id。 | assistant_service_records.json - data.orderAssistantDetails - order_pay_id。 |
+
+| `order_assistant_id` | BIGINT | | | 订单中“助教项目明细”的内部 ID。;用途:如果订单里有多条助教项目(比如换助教、多个时间段),此字段唯一标识这一条助教明细;用于跨表关联与去重。 | assistant_service_records - order_assistant_id。 | assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。 |
+
+| `order_assistant_type` | INTEGER | | | 1:常规助教服务(主课/基础课)。 | assistant_service_records - order_assistant_type。 | assistant_service_records.json - data.orderAssistantDetails - order_assistant_type。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID;你这份数据中是固定值(同一个商户)。;关联:全库所有表都有,作为“商户维度”的过滤键;用途:多租户数据隔离与按租户汇总。 | assistant_service_records - tenant_id。 | assistant_service_records.json - data.orderAssistantDetails - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,本数据中指“朗朗桌球”这一家门店。;关联:与其他所有 JSON 中的 site_id 一致,用于判断记录属于哪家门店。 | assistant_service_records - site_id。 | assistant_service_records.json - data.orderAssistantDetails - site_id。 |
+
+| `site_table_id` | BIGINT | | | 球台 ID。;关联:对应台桌列表中的 id 字段,表示具体是哪一张桌;用于跨表关联与去重。 | assistant_service_records - site_table_id。 | assistant_service_records.json - data.orderAssistantDetails - site_table_id。 |
+
+| `tenant_member_id` | BIGINT | | | 商户维度会员 ID(门店/品牌内的会员主键)。;关联:**会员档案(tenantMemberInfos)**中的 id = 此处的 tenant_member_id;用于跨表关联与去重。 | assistant_service_records - tenant_member_id。 | assistant_service_records.json - data.orderAssistantDetails - tenant_member_id。 |
+
+| `system_member_id` | BIGINT | | | 系统级会员 ID(全集团统一 ID)。;关联:会员档案中的 system_member_id 字段;用于跨表关联与去重。 | assistant_service_records - system_member_id。 | assistant_service_records.json - data.orderAssistantDetails - system_member_id。 |
+
+| `assistant_no` | VARCHAR(64) | | | 助教编号,例如 "27"。;关联:在助教账号表里也有 assistant_no 字段,对应工号/编号。 | assistant_service_records - assistantNo。 | assistant_service_records.json - data.orderAssistantDetails - assistantNo。 |
+
+| `nickname` | VARCHAR(64) | | | 助教对外昵称,如“佳怡”“周周”“球球”等。;关联:在很多小票、商品名里,会把 “编号-昵称” 组合使用(如 ledger_name = "2-佳怡")。 | assistant_service_records - nickname。 | assistant_service_records.json - data.orderAssistantDetails - nickname。 |
+
+| `site_assistant_id` | BIGINT | | | 订单中“助教项目明细”的内部 ID。;用途:如果订单里有多条助教项目(比如换助教、多个时间段),此字段唯一标识这一条助教明细;用于跨表关联与去重。 | assistant_service_records - order_assistant_id。 | assistant_service_records.json - data.orderAssistantDetails - order_assistant_id。 |
+
+| `user_id` | BIGINT | | | 助教对应的“用户账号 ID”(系统级用户)。;关联:在助教账号表中有同名字段 user_id,与这里完全一致;用于跨表关联与去重。 | assistant_service_records - user_id。 | assistant_service_records.json - data.orderAssistantDetails - user_id。 |
+
+| `assistant_team_id` | BIGINT | | | 助教所属团队 ID。;关联:在助教账号表中有 team_id 字段,对应相同值;用于跨表关联与去重。 | assistant_service_records - assistant_team_id。 | assistant_service_records.json - data.orderAssistantDetails - assistant_team_id。 |
+
+| `person_org_id` | BIGINT | | | 助教所属“人事组织/部门 ID”。;关联:在助教账号表中同样存在 person_org_id 字段,值完全一致;用于跨表关联与去重。 | assistant_service_records - person_org_id。 | assistant_service_records.json - data.orderAssistantDetails - person_org_id。 |
+
+| `assistant_level` | INTEGER | | | 业务明细字段,用于补充该记录的业务属性。 | assistant_service_records - assistant_level。 | assistant_service_records.json - data.orderAssistantDetails - assistant_level。 |
+
+| `level_name` | VARCHAR(64) | | | 助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。 | assistant_service_records - levelName。 | assistant_service_records.json - data.orderAssistantDetails - levelName。 |
+
+| `skill_id` | BIGINT | | | 助教服务“课程/技能”ID。;关联:应对应某个“课程/技能配置表”的主键(你这次导出里没见那个表);用于跨表关联与去重。 | assistant_service_records - skill_id。 | assistant_service_records.json - data.orderAssistantDetails - skill_id。 |
+
+| `skill_name` | VARCHAR(64) | | | 当前这条助教服务所对应的“课程/技能名称”。 | assistant_service_records - skillName。 | assistant_service_records.json - data.orderAssistantDetails - skillName。 |
+
+| `ledger_unit_price` | NUMERIC(10,2) | | | 助教服务 标准单价(通常是标价:每小时、每节课的单价)。 | assistant_service_records - ledger_unit_price。 | assistant_service_records.json - data.orderAssistantDetails - ledger_unit_price。 |
+
+| `ledger_amount` | NUMERIC(10,2) | | | 按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。 | assistant_service_records - ledger_amount。 | assistant_service_records.json - data.orderAssistantDetails - ledger_amount。 |
+
+| `projected_income` | NUMERIC(10,2) | | | 实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。 | assistant_service_records - projected_income。 | assistant_service_records.json - data.orderAssistantDetails - projected_income。 |
+
+| `coupon_deduct_money` | NUMERIC(10,2) | | | 由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。 | assistant_service_records - coupon_deduct_money。 | assistant_service_records.json - data.orderAssistantDetails - coupon_deduct_money。 |
+
+| `income_seconds` | INTEGER | | | 计费秒数 / 应计收入对应的时间。 | assistant_service_records - income_seconds。 | assistant_service_records.json - data.orderAssistantDetails - income_seconds。 |
+
+| `real_use_seconds` | INTEGER | | | 实际使用时长(秒)。 | assistant_service_records - real_use_seconds。 | assistant_service_records.json - data.orderAssistantDetails - real_use_seconds。 |
+
+| `add_clock` | INTEGER | | | 加钟秒数,即在原有预约/服务基础上临时追加的时长。 | assistant_service_records - add_clock。 | assistant_service_records.json - data.orderAssistantDetails - add_clock。 |
+
+| `create_time` | TIMESTAMPTZ | | | 这条助教流水记录创建时间(一般接近结算/下单时间);记录源系统创建时间,用于增量同步和口径对齐。 | assistant_service_records - create_time。 | assistant_service_records.json - data.orderAssistantDetails - create_time。 |
+
+| `start_use_time` | TIMESTAMPTZ | | | 助教实际开始服务时间。 | assistant_service_records - start_use_time。 | assistant_service_records.json - data.orderAssistantDetails - start_use_time。 |
+
+| `last_use_time` | TIMESTAMPTZ | | | 最后一次使用(实际服务)时间。 | assistant_service_records - last_use_time。 | assistant_service_records.json - data.orderAssistantDetails - last_use_time。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志。;注意:这份助教流水里没有直接出现“顾客姓名”字段,只通过这两个 ID 与会员档案、储值卡等表关联;软删除/作废标记,分析通常需过滤为有效记录。 | assistant_service_records - is_delete。 | assistant_service_records.json - data.orderAssistantDetails - is_delete。 |
+
+
+
+## `dwd_assistant_trash_event`
+
+
+
+- 表说明:DWD 明细事实表:dwd_assistant_trash_event。ODS 来源表:billiards_ods.assistant_cancellation_records(对应 JSON:assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:assistant_trash_event_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `assistant_trash_event_id` | BIGINT | Y | | 助教trashevent ID(源系统唯一标识),用于跨表关联、去重与维度汇总。 | assistant_cancellation_records - id。 | assistant_cancellation_records.json - data.abolitionAssistants - id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,即该废除记录所在门店。;关联:与 siteProfile.id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | assistant_cancellation_records - siteId。 | assistant_cancellation_records.json - data.abolitionAssistants - siteId。 |
+
+| `table_id` | BIGINT | | dim_table(table_id) | 球台/桌子的 ID。;关联:对应 “台桌列表.json” 中的 id 字段;用于跨表关联与去重。 | assistant_cancellation_records - tableId。 | assistant_cancellation_records.json - data.abolitionAssistants - tableId。 |
+
+| `table_area_id` | BIGINT | | | 台桌所在区域 ID。;关联:应对应“区域配置表”的主键(本次导出未包含该表);用于跨表关联与去重。 | assistant_cancellation_records - tableAreaId。 | assistant_cancellation_records.json - data.abolitionAssistants - tableAreaId。 |
+
+| `assistant_no` | VARCHAR(32) | | | 助教姓名/对外展示名称。;注意:这是被废除的那位助教,不是顾客姓名。 | assistant_cancellation_records - assistantName。 | assistant_cancellation_records.json - data.abolitionAssistants - assistantName。 |
+
+| `assistant_name` | VARCHAR(64) | | | 助教姓名/对外展示名称。;注意:这是被废除的那位助教,不是顾客姓名。 | assistant_cancellation_records - assistantName。 | assistant_cancellation_records.json - data.abolitionAssistants - assistantName。 |
+
+| `charge_minutes_raw` | INTEGER | | | “已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟。 | assistant_cancellation_records - pdChargeMinutes。 | assistant_cancellation_records.json - data.abolitionAssistants - pdChargeMinutes。 |
+
+| `abolish_amount` | NUMERIC(18,2) | | | 与“助教废除”关联的金额字段。字面上是“助教废除金额”。 | assistant_cancellation_records - assistantAbolishAmount。 | assistant_cancellation_records.json - data.abolitionAssistants - assistantAbolishAmount。 |
+
+| `trash_reason` | VARCHAR(255) | | | 用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等。 | assistant_cancellation_records - trashReason。 | assistant_cancellation_records.json - data.abolitionAssistants - trashReason。 |
+
+| `create_time` | TIMESTAMPTZ | | | 这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻;记录源系统创建时间,用于增量同步和口径对齐。 | assistant_cancellation_records - createTime。 | assistant_cancellation_records.json - data.abolitionAssistants - createTime。 |
+
+
+
+## `dwd_groupbuy_redemption`
+
+
+
+- 表说明:DWD 明细事实表:dwd_groupbuy_redemption。ODS 来源表:billiards_ods.group_buy_redemption_records(对应 JSON:group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:redemption_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `redemption_id` | BIGINT | Y | | 本条“团购套餐流水”记录的 主键 ID。;用途:唯一标识一条券使用到台费上的记录;用于跨表关联与去重。 | group_buy_redemption_records - id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID;用途:多租户数据隔离与按租户汇总。 | group_buy_redemption_records - tenant_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,与其它 JSON 中一致。;关联:与“团购套餐定义”、“助教流水”、“台费流水”、“门店销售记录”等文件中的 site_id 完全一致,用于统一按门店过滤。 | group_buy_redemption_records - site_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - site_id。 |
+
+| `table_id` | BIGINT | | dim_table(table_id) | 球台 ID。;关联:对应“台桌列表”表中的 id 字段;用于跨表关联与去重。 | group_buy_redemption_records - table_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - table_id。 |
+
+| `tenant_table_area_id` | BIGINT | | | 租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。;关联:与“团购套餐定义”中的 tenant_table_area_id_list 对应(那边是字符串形态,这里是数值形态),表明该券只能在某些台区组合上使用;用于跨表关联与去重。 | group_buy_redemption_records - tenant_table_area_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - tenant_table_area_id。 |
+
+| `table_charge_seconds` | INTEGER | | | 本次结算中该球台总计计费的秒数(整台的台费计费时间)。 | group_buy_redemption_records - table_charge_seconds。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - table_charge_seconds。 |
+
+| `order_trade_no` | BIGINT | | | 订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。;关联:与“小票详情”、“台费流水”、“助教流水”等的 order_trade_no 一致,用于将同一笔结账中的所有子项目关联起来。 | group_buy_redemption_records - order_trade_no。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - order_trade_no。 |
+
+| `order_settle_id` | BIGINT | | dwd_settlement_head(order_settle_id) | 结算单 ID(小票结账主键)。;关联:与“小票详情”中的 orderSettleId 相对应;用于跨表关联与去重。 | group_buy_redemption_records - order_settle_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - order_settle_id。 |
+
+| `order_coupon_id` | BIGINT | | | 订单中“券使用记录”的 ID;用于跨表关联与去重。 | group_buy_redemption_records - order_coupon_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_id。 |
+
+| `coupon_origin_id` | BIGINT | | | 平台/上游系统中的券记录主键 ID,“券来源 ID”;用于跨表关联与去重。 | group_buy_redemption_records - coupon_origin_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_origin_id。 |
+
+| `promotion_activity_id` | BIGINT | | | 团购/促销活动 ID;用于跨表关联与去重。 | group_buy_redemption_records - promotion_activity_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_activity_id。 |
+
+| `promotion_coupon_id` | BIGINT | | | 团购套餐定义 ID。;关联:与 20251110_043255_团购套餐.json 中的 id 字段一一对应,即:;用于跨表关联与去重。 | group_buy_redemption_records - promotion_coupon_id。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_coupon_id。 |
+
+| `order_coupon_channel` | INTEGER | | | 券渠道类型,例如:。 | group_buy_redemption_records - order_coupon_channel。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - order_coupon_channel。 |
+
+| `ledger_unit_price` | NUMERIC(18,2) | | | 对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。;用途:配合 ledger_count 用于计算这一条券在台费层面对应的金额(理论上应接近 = 单价 × 秒数/3600)。 | group_buy_redemption_records - ledger_unit_price。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_unit_price。 |
+
+| `ledger_count` | INTEGER | | | 按此次优惠实际计算的“核销秒数”。 | group_buy_redemption_records - ledger_count。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_count。 |
+
+| `ledger_amount` | NUMERIC(18,2) | | | 本次券实际冲抵台费的金额。 | group_buy_redemption_records - ledger_amount。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_amount。 |
+
+| `coupon_money` | NUMERIC(18,2) | | | 本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。 | group_buy_redemption_records - coupon_money。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_money。 |
+
+| `promotion_seconds` | INTEGER | | | 团购套餐定义的“标准时长”(券本身标称的可用时长)。 | group_buy_redemption_records - promotion_seconds。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - promotion_seconds。 |
+
+| `coupon_code` | VARCHAR(64) | | | 团购券券码,核销时扫描/录入的字符串。;关联:与平台验券记录表中的 coupon_code 完全一致,通过该字段可以串起“平台 → 核销 → 台费流水”全链路。 | group_buy_redemption_records - coupon_code。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - coupon_code。 |
+
+| `is_single_order` | INTEGER | | | 是否单独作为一条订单行。 | group_buy_redemption_records - is_single_order。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - is_single_order。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志:;软删除/作废标记,分析通常需过滤为有效记录。 | group_buy_redemption_records - is_delete。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - is_delete。 |
+
+| `ledger_name` | VARCHAR(128) | | | 台费侧关联的“团购项目名称”(记账名)。 | group_buy_redemption_records - ledger_name。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - ledger_name。 |
+
+| `create_time` | TIMESTAMPTZ | | | 本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近);记录源系统创建时间,用于增量同步和口径对齐。 | group_buy_redemption_records - create_time。 | group_buy_redemption_records.json - data.siteTableUseDetailsList - create_time。 |
+
+
+
+## `dwd_member_balance_change`
+
+
+
+- 表说明:DWD 明细事实表:dwd_member_balance_change。ODS 来源表:billiards_ods.member_balance_changes(对应 JSON:member_balance_changes.json;分析:member_balance_changes-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:balance_change_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `balance_change_id` | BIGINT | Y | | 余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”;用于跨表关联与去重。 | member_balance_changes - id。 | member_balance_changes.json - data.tenantMemberCardLogs - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/商户 ID,本数据中是固定值(同一品牌/商户);用途:多租户数据隔离与按租户汇总。 | member_balance_changes - tenant_id。 | member_balance_changes.json - data.tenantMemberCardLogs - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致)。;关联:可与门店档案(siteProfile.id)对应;用途:门店维度分组、计营业额、与门店档案关联。 | member_balance_changes - site_id。 | member_balance_changes.json - data.tenantMemberCardLogs - site_id。 |
+
+| `register_site_id` | BIGINT | | | 会员卡的“注册门店 ID”,即办卡所在门店;用于跨表关联与去重。 | member_balance_changes - register_site_id。 | member_balance_changes.json - data.tenantMemberCardLogs - register_site_id。 |
+
+| `tenant_member_id` | BIGINT | | | 商户维度的会员 ID(租户内会员主键)。;用途:在本表与会员档案之间形成外键关系: 余额变更记录.tenant_member_id = 会员档案.id;关联:对应“会员档案(20251110_043209_…)”中的 id 字段,即同一个租户下的会员主键;用于跨表关联与去重。 | member_balance_changes - tenant_member_id。 | member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_id。 |
+
+| `system_member_id` | BIGINT | | | 系统级(全局)会员 ID。;关联:对应会员档案中的 system_member_id 字段;用于跨表关联与去重。 | member_balance_changes - system_member_id。 | member_balance_changes.json - data.tenantMemberCardLogs - system_member_id。 |
+
+| `tenant_member_card_id` | BIGINT | | | 会员卡账户 ID,在租户内唯一标识某张卡。;用途:一名会员可以有多张卡(储值卡、台费卡、酒水卡、活动券等),tenant_member_card_id 指明这条余额变更是针对哪一张卡。;关联:对应“会员档案/储值卡列表”中的 id(卡账户 ID);用于跨表关联与去重。 | member_balance_changes - tenant_member_card_id。 | member_balance_changes.json - data.tenantMemberCardLogs - tenant_member_card_id。 |
+
+| `card_type_id` | BIGINT | | | 卡种类型 ID,用于区分不同卡种。 | member_balance_changes - card_type_id。 | member_balance_changes.json - data.tenantMemberCardLogs - card_type_id。 |
+
+| `card_type_name` | VARCHAR(32) | | | 卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。 | member_balance_changes - memberCardTypeName。 | member_balance_changes.json - data.tenantMemberCardLogs - memberCardTypeName。 |
+
+| `member_name` | VARCHAR(64) | | | 会员姓名或称呼(非昵称字段)。 | member_balance_changes - memberName。 | member_balance_changes.json - data.tenantMemberCardLogs - memberName。 |
+
+| `member_mobile` | VARCHAR(20) | | | 会员手机号;手机号码,用于账户/会员识别、查询与联系。 | member_balance_changes - memberMobile。 | member_balance_changes.json - data.tenantMemberCardLogs - memberMobile。 |
+
+| `balance_before` | NUMERIC(18,2) | | | 本次变动前,该卡账户的余额(元)。 | member_balance_changes - before。 | member_balance_changes.json - data.tenantMemberCardLogs - before。 |
+
+| `change_amount` | NUMERIC(18,2) | | | 本次变动的金额(元),正数表示增加,负数表示减少。 | member_balance_changes - account_data。 | member_balance_changes.json - data.tenantMemberCardLogs - account_data。 |
+
+| `balance_after` | NUMERIC(18,2) | | | 本次变动后,该卡账户的余额(元)。 | member_balance_changes - after。 | member_balance_changes.json - data.tenantMemberCardLogs - after。 |
+
+| `from_type` | INTEGER | | | 1:日常消费扣款。 | member_balance_changes - from_type。 | member_balance_changes.json - data.tenantMemberCardLogs - from_type。 |
+
+| `payment_method` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | member_balance_changes - payment_method。 | member_balance_changes.json - data.tenantMemberCardLogs - payment_method。 |
+
+| `change_time` | TIMESTAMPTZ | | | 本条余额变更记录的创建时间,通常接近交易发生时间。 | member_balance_changes - create_time。 | member_balance_changes.json - data.tenantMemberCardLogs - create_time。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标记:;软删除/作废标记,分析通常需过滤为有效记录。 | member_balance_changes - is_delete。 | member_balance_changes.json - data.tenantMemberCardLogs - is_delete。 |
+
+| `remark` | VARCHAR(255) | | | 当为空时,说明这条变动没有额外备注说明。 | member_balance_changes - remark。 | member_balance_changes.json - data.tenantMemberCardLogs - remark。 |
+
+
+
+## `dwd_payment`
+
+
+
+- 表说明:DWD 明细事实表:dwd_payment。ODS 来源表:billiards_ods.payment_transactions(对应 JSON:payment_transactions.json;分析:payment_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:payment_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `payment_id` | BIGINT | Y | | 支付流水记录的主键 ID。;用途:在“支付记录”这个表内部,唯一标识一条支付流水(包括金额为 0 的记录);用于跨表关联与去重。 | payment_transactions - id。 | payment_transactions.json - $ - id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 支付记录所属的门店 ID;用途:门店维度分组、计营业额、与门店档案关联。 | payment_transactions - site_id。 | payment_transactions.json - $ - site_id。 |
+
+| `relate_type` | INTEGER | | | 表示“这条支付记录关联的业务类型”。 | payment_transactions - relate_type。 | payment_transactions.json - $ - relate_type。 |
+
+| `relate_id` | BIGINT | | | 关联业务记录的主键 ID(按 relate_type 不同指向不同表);用于跨表关联与去重。 | payment_transactions - relate_id。 | payment_transactions.json - $ - relate_id。 |
+
+| `pay_amount` | NUMERIC(18,2) | | | 本条支付流水的“支付金额”,单位为元。 | payment_transactions - pay_amount。 | payment_transactions.json - $ - pay_amount。 |
+
+| `pay_status` | INTEGER | | | 支付状态枚举字段。 | payment_transactions - pay_status。 | payment_transactions.json - $ - pay_status。 |
+
+| `payment_method` | INTEGER | | | 支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种。 | payment_transactions - payment_method。 | payment_transactions.json - $ - payment_method。 |
+
+| `online_pay_channel` | INTEGER | | | 线上支付渠道枚举,例如:。 | payment_transactions - online_pay_channel。 | payment_transactions.json - $ - online_pay_channel。 |
+
+| `create_time` | TIMESTAMPTZ | | | 支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳);记录源系统创建时间,用于增量同步和口径对齐。 | payment_transactions - create_time。 | payment_transactions.json - $ - create_time。 |
+
+| `pay_time` | TIMESTAMPTZ | | | 实际支付完成时间(支付状态变为成功的时间戳)。 | payment_transactions - pay_time。 | payment_transactions.json - $ - pay_time。 |
+
+| `pay_date` | DATE | | | 业务明细字段,用于补充该记录的业务属性。 | payment_transactions - pay_time(派生:DATE(pay_time))。 | payment_transactions.json - $ - pay_time(派生:DATE(pay_time))。 |
+
+
+
+## `dwd_platform_coupon_redemption`
+
+
+
+- 表说明:DWD 明细事实表:dwd_platform_coupon_redemption。ODS 来源表:billiards_ods.platform_coupon_redemption_records(对应 JSON:platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:platform_coupon_redemption_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `platform_coupon_redemption_id` | BIGINT | Y | | 本条平台验券记录在本系统内的主键 ID;用于跨表关联与去重。 | platform_coupon_redemption_records - id。 | platform_coupon_redemption_records.json - $ - id。 |
+
+| `tenant_id` | BIGINT | | | 商户/租户 ID(品牌级别)。;关联:与其他所有 JSON 中的 tenant_id 一致,用于区分不同品牌/商户的数据域。 | platform_coupon_redemption_records - tenant_id。 | platform_coupon_redemption_records.json - $ - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID。;关联:对应 siteProfile.id;用途:门店维度分组、计营业额、与门店档案关联。 | platform_coupon_redemption_records - site_id。 | platform_coupon_redemption_records.json - $ - site_id。 |
+
+| `coupon_code` | VARCHAR(64) | | | 券码,顾客出示的团购券密码/编号。 | platform_coupon_redemption_records - coupon_code。 | platform_coupon_redemption_records.json - $ - coupon_code。 |
+
+| `coupon_channel` | INTEGER | | | 券来源渠道(第三方平台渠道编号)。 | platform_coupon_redemption_records - coupon_channel。 | platform_coupon_redemption_records.json - $ - coupon_channel。 |
+
+| `coupon_name` | VARCHAR(200) | | | 团购券产品名称(即第三方平台上向顾客展示的名称)。 | platform_coupon_redemption_records - coupon_name。 | platform_coupon_redemption_records.json - $ - coupon_name。 |
+
+| `sale_price` | NUMERIC(10,2) | | | 顾客在第三方平台上实际支付的价格(团购售价)。 | platform_coupon_redemption_records - sale_price。 | platform_coupon_redemption_records.json - $ - sale_price。 |
+
+| `coupon_money` | NUMERIC(10,2) | | | 券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”)。 | platform_coupon_redemption_records - coupon_money。 | platform_coupon_redemption_records.json - $ - coupon_money。 |
+
+| `coupon_free_time` | INTEGER | | | 券附带的“免费时长”字段(例如送多少分钟台费)。 | platform_coupon_redemption_records - coupon_free_time。 | platform_coupon_redemption_records.json - $ - coupon_free_time。 |
+
+| `channel_deal_id` | BIGINT | | | 渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键;用于跨表关联与去重。 | platform_coupon_redemption_records - channel_deal_id。 | platform_coupon_redemption_records.json - $ - channel_deal_id。 |
+
+| `deal_id` | BIGINT | | | 另一个层次的团购产品 ID;用于跨表关联与去重。 | platform_coupon_redemption_records - deal_id。 | platform_coupon_redemption_records.json - $ - deal_id。 |
+
+| `group_package_id` | BIGINT | | | group套餐 ID(源系统唯一标识),用于跨表关联、去重与维度汇总。 | platform_coupon_redemption_records - group_package_id。 | platform_coupon_redemption_records.json - $ - group_package_id。 |
+
+| `site_order_id` | BIGINT | | | 门店内部的订单 ID(平台券核销时对应的店内订单)。;关联:与台费流水、门店销售记录、助教流水等中出现的订单 ID 字段对应,用于把“平台券核销记录”挂到一笔本地订单上。 | platform_coupon_redemption_records - site_order_id。 | platform_coupon_redemption_records.json - $ - site_order_id。 |
+
+| `table_id` | BIGINT | | dim_table(table_id) | 使用券的球台 ID。;关联:与“台桌列表”中的 id 对应;用于跨表关联与去重。 | platform_coupon_redemption_records - table_id。 | platform_coupon_redemption_records.json - $ - table_id。 |
+
+| `certificate_id` | VARCHAR(64) | | | 平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID);用于跨表关联与去重。 | platform_coupon_redemption_records - certificate_id。 | platform_coupon_redemption_records.json - $ - certificate_id。 |
+
+| `verify_id` | VARCHAR(64) | | | 平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID);用于跨表关联与去重。 | platform_coupon_redemption_records - verify_id。 | platform_coupon_redemption_records.json - $ - verify_id。 |
+
+| `use_status` | INTEGER | | | 1:已使用 / 已核销(正常消耗)。 | platform_coupon_redemption_records - use_status。 | platform_coupon_redemption_records.json - $ - use_status。 |
+
+| `is_delete` | INTEGER | | | 0:未删除;用途:把平台验券记录挂到本门店的一条订单上;软删除/作废标记,分析通常需过滤为有效记录。 | platform_coupon_redemption_records - is_delete。 | platform_coupon_redemption_records.json - $ - is_delete。 |
+
+| `create_time` | TIMESTAMPTZ | | | 验券记录在本系统中创建的时间(记录入库时间);记录源系统创建时间,用于增量同步和口径对齐。 | platform_coupon_redemption_records - create_time。 | platform_coupon_redemption_records.json - $ - create_time。 |
+
+| `consume_time` | TIMESTAMPTZ | | | 券被核销/使用的业务时间。 | platform_coupon_redemption_records - consume_time。 | platform_coupon_redemption_records.json - $ - consume_time。 |
+
+
+
+## `dwd_recharge_order`
+
+
+
+- 表说明:DWD 明细事实表:dwd_recharge_order。ODS 来源表:billiards_ods.recharge_settlements(对应 JSON:recharge_settlements.json;分析:recharge_settlements-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:recharge_order_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `recharge_order_id` | BIGINT | Y | | 门店 ID;用于跨表关联与去重。 | recharge_settlements - id。 | recharge_settlements.json - $ - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID,和 siteProfile.tenant_id 一致;用途:多租户数据隔离与按租户汇总。 | recharge_settlements - tenantid。 | recharge_settlements.json - $ - tenantid。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,和 siteProfile.id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | recharge_settlements - siteid。 | recharge_settlements.json - $ - siteid。 |
+
+| `member_id` | BIGINT | | dim_member(member_id) | 会员档案的主键 ID。;关联:对应“会员档案.json”中 tenantMemberInfos 的 id 字段(部分成员能直接匹配);用于跨表关联与去重。 | recharge_settlements - memberid。 | recharge_settlements.json - $ - memberid。 |
+
+| `member_name_snapshot` | TEXT | | | 会员名称/昵称快照。 | recharge_settlements - membername。 | recharge_settlements.json - $ - membername。 |
+
+| `member_phone_snapshot` | TEXT | | | 会员手机号快照,用于查找和展示。 | recharge_settlements - memberphone。 | recharge_settlements.json - $ - memberphone。 |
+
+| `tenant_member_card_id` | BIGINT | | | 会员卡实例 ID(某张具体卡);用于跨表关联与去重。 | recharge_settlements - tenantmembercardid。 | recharge_settlements.json - $ - tenantmembercardid。 |
+
+| `member_card_type_name` | TEXT | | | 本次充值针对的会员卡类型名称。 | recharge_settlements - membercardtypename。 | recharge_settlements.json - $ - membercardtypename。 |
+
+| `settle_relate_id` | BIGINT | | | 关联的“结算单/业务单”ID;用于跨表关联与去重。 | recharge_settlements - settlerelateid。 | recharge_settlements.json - $ - settlerelateid。 |
+
+| `settle_type` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | recharge_settlements - settletype。 | recharge_settlements.json - $ - settletype。 |
+
+| `settle_name` | TEXT | | | 业务类型名称,用于前端展示。 | recharge_settlements - settlename。 | recharge_settlements.json - $ - settlename。 |
+
+| `is_first` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | recharge_settlements - isfirst。 | recharge_settlements.json - $ - isfirst。 |
+
+| `pay_amount` | NUMERIC(18,2) | | | 本次记录对应的充值金额(含正负)。 | recharge_settlements - payamount。 | recharge_settlements.json - $ - payamount。 |
+
+| `refund_amount` | NUMERIC(18,2) | | | 针对本条充值订单所做的退款金额(通常为正数)。 | recharge_settlements - refundamount。 | recharge_settlements.json - $ - refundamount。 |
+
+| `point_amount` | NUMERIC(18,2) | | | 计入会员账户的“储值金额”或“积分型金额”。 | recharge_settlements - pointamount。 | recharge_settlements.json - $ - pointamount。 |
+
+| `cash_amount` | NUMERIC(18,2) | | | 现金收款金额。 | recharge_settlements - cashamount。 | recharge_settlements.json - $ - cashamount。 |
+
+| `payment_method` | INTEGER | | | 支付方式编码。 | recharge_settlements - paymentmethod。 | recharge_settlements.json - $ - paymentmethod。 |
+
+| `create_time` | TIMESTAMPTZ | | | 充值记录创建时间,一般即收银完成时间;记录源系统创建时间,用于增量同步和口径对齐。 | recharge_settlements - createtime。 | recharge_settlements.json - $ - createtime。 |
+
+| `pay_time` | TIMESTAMPTZ | | | 支付完成时间。 | recharge_settlements - paytime。 | recharge_settlements.json - $ - paytime。 |
+
+
+
+## `dwd_refund`
+
+
+
+- 表说明:DWD 明细事实表:dwd_refund。ODS 来源表:billiards_ods.refund_transactions(对应 JSON:refund_transactions.json;分析:refund_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:refund_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `refund_id` | BIGINT | Y | | 本条 退款流水 的唯一 ID。;用途:作为退款记录表主键,内部检索用;用于跨表关联与去重。 | refund_transactions - id。 | refund_transactions.json - $ - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID,全系统维度标识该商户。;用途:作为所有门店数据的“租户分区键”;用途:多租户数据隔离与按租户汇总。 | refund_transactions - tenant_id。 | refund_transactions.json - $ - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID。;用途:关联其他数据表中同一门店的数据;用途:门店维度分组、计营业额、与门店档案关联。 | refund_transactions - site_id。 | refund_transactions.json - $ - site_id。 |
+
+| `relate_type` | INTEGER | | | 本退款对应的“业务类型”。 | refund_transactions - relate_type。 | refund_transactions.json - $ - relate_type。 |
+
+| `relate_id` | BIGINT | | | 本次退款关联的业务 ID;用于跨表关联与去重。 | refund_transactions - relate_id。 | refund_transactions.json - $ - relate_id。 |
+
+| `pay_amount` | NUMERIC(18,2) | | | 本次退款的 资金变动金额。 | refund_transactions - pay_amount。 | refund_transactions.json - $ - pay_amount。 |
+
+| `channel_fee` | NUMERIC(18,2) | | | 第三方支付渠道对本次退款收取的手续费。 | refund_transactions - channel_fee。 | refund_transactions.json - $ - channel_fee。 |
+
+| `pay_time` | TIMESTAMPTZ | | | 退款在支付渠道层面实际发生的时间。 | refund_transactions - pay_time。 | refund_transactions.json - $ - pay_time。 |
+
+| `create_time` | TIMESTAMPTZ | | | 本条退款流水在系统内创建时间;记录源系统创建时间,用于增量同步和口径对齐。 | refund_transactions - create_time。 | refund_transactions.json - $ - create_time。 |
+
+| `payment_method` | INTEGER | | | 支付/退款的 方式类型:。 | refund_transactions - payment_method。 | refund_transactions.json - $ - payment_method。 |
+
+| `member_id` | BIGINT | | dim_member(member_id) | 租户内部的会员 ID(对应会员档案中的某个主键);用于跨表关联与去重。 | refund_transactions - member_id。 | refund_transactions.json - $ - member_id。 |
+
+| `member_card_id` | BIGINT | | dim_member_card_account(member_card_id) | 关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡);用于跨表关联与去重。 | refund_transactions - member_card_id。 | refund_transactions.json - $ - member_card_id。 |
+
+
+
+## `dwd_settlement_head`
+
+
+
+- 表说明:DWD 明细事实表:dwd_settlement_head。ODS 来源表:billiards_ods.settlement_records(对应 JSON:settlement_records.json;分析:settlement_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:order_settle_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `order_settle_id` | BIGINT | Y | | 结账记录主键 ID(订单结算 ID)。;关联:与台费流水(siteTableUseDetailsList)中的 order_settle_id 一致;用于跨表关联与去重。 | settlement_records - id。 | settlement_records.json - $ - id。 |
+
+| `tenant_id` | BIGINT | | | 租户/商户 ID(品牌维度);用途:多租户数据隔离与按租户汇总。 | settlement_records - tenantid。 | settlement_records.json - $ - tenantid。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID。;关联:与其他所有 JSON 中的 site_id 对应;用途:门店维度分组、计营业额、与门店档案关联。 | settlement_records - siteid。 | settlement_records.json - $ - siteid。 |
+
+| `site_name` | VARCHAR(100) | | | 门店名称,冗余展示字段。 | settlement_records - sitename。 | settlement_records.json - $ - sitename。 |
+
+| `table_id` | BIGINT | | dim_table(table_id) | 本次结账对应的桌台 ID。;关联:对应台桌维表或台费流水中的 site_table_id;用于跨表关联与去重。 | settlement_records - tableid。 | settlement_records.json - $ - tableid。 |
+
+| `settle_name` | VARCHAR(100) | | | 结账对象名称,一般是“区域 + 桌号”的组合。 | settlement_records - settlename。 | settlement_records.json - $ - settlename。 |
+
+| `order_trade_no` | BIGINT | | | 关联订单的“交易号”(order_trade_no)。;关联:与台费流水(order_trade_no)、助教流水(order_trade_no)中的该字段完全一致。 | settlement_records - settlerelateid。 | settlement_records.json - $ - settlerelateid。 |
+
+| `create_time` | TIMESTAMPTZ | | | 结账记录创建时间,一般对应收银端点“确认结账”的时间;记录源系统创建时间,用于增量同步和口径对齐。 | settlement_records - createtime。 | settlement_records.json - $ - createtime。 |
+
+| `pay_time` | TIMESTAMPTZ | | | 实际支付完成时间。通常晚于 createTime(比如多支付场景)。 | settlement_records - paytime。 | settlement_records.json - $ - paytime。 |
+
+| `settle_type` | INTEGER | | | 代表结账类型,比如:。 | settlement_records - settletype。 | settlement_records.json - $ - settletype。 |
+
+| `revoke_order_id` | BIGINT | | | 若当前记录是“被撤销的单”,则记录对应的“撤销单 ID”;或反过来记录“原单 ID”;用于跨表关联与去重。 | settlement_records - revokeorderid。 | settlement_records.json - $ - revokeorderid。 |
+
+| `member_id` | BIGINT | | dim_member(member_id) | 会员主键 ID。;关联:与“会员卡列表(tenantMemberCards)”中的 tenant_member_id 一致;用于跨表关联与去重。 | settlement_records - memberid。 | settlement_records.json - $ - memberid。 |
+
+| `member_name` | VARCHAR(100) | | | 会员姓名快照。 | settlement_records - membername。 | settlement_records.json - $ - membername。 |
+
+| `member_phone` | VARCHAR(50) | | | 会员手机号快照;手机号码,用于账户/会员识别、查询与联系。 | settlement_records - memberphone。 | settlement_records.json - $ - memberphone。 |
+
+| `member_card_account_id` | BIGINT | | | 会员卡账户 ID(与 memberId、会员卡表的 id 之间存在映射);用于跨表关联与去重。 | settlement_records - tenantmembercardid。 | settlement_records.json - $ - tenantmembercardid。 |
+
+| `member_card_type_name` | VARCHAR(100) | | | 会员卡类型名称,如“储值卡”“次卡”“活动抵用券”等。 | settlement_records - membercardtypename。 | settlement_records.json - $ - membercardtypename。 |
+
+| `is_bind_member` | BOOLEAN | | | 本次结账是否绑定了会员。 | settlement_records - isbindmember。 | settlement_records.json - $ - isbindmember。 |
+
+| `member_discount_amount` | NUMERIC(18,2) | | | 会员折扣产生的优惠金额(元)。 | settlement_records - memberdiscountamount。 | settlement_records.json - $ - memberdiscountamount。 |
+
+| `consume_money` | NUMERIC(18,2) | | | 本次结账消费总额(不考虑支付方式/优惠结构的前后顺序,单纯汇总项目金额)。 | settlement_records - consumemoney。 | settlement_records.json - $ - consumemoney。 |
+
+| `table_charge_money` | NUMERIC(18,2) | | | 台费(桌台计费部分)的金额。 | settlement_records - tablechargemoney。 | settlement_records.json - $ - tablechargemoney。 |
+
+| `goods_money` | NUMERIC(18,2) | | | 商品销售金额(原始商品金额)。 | settlement_records - goodsmoney。 | settlement_records.json - $ - goodsmoney。 |
+
+| `real_goods_money` | NUMERIC(18,2) | | | 商品实际计入金额(可能已扣除某些折扣、促销)。 | settlement_records - realgoodsmoney。 | settlement_records.json - $ - realgoodsmoney。 |
+
+| `assistant_pd_money` | NUMERIC(18,2) | | | 助教“排钟/上课”应计金额(原价)。;关联:与 助教流水.json 中对应订单的 ledger_amount 一致(应收金额)。 | settlement_records - assistantpdmoney。 | settlement_records.json - $ - assistantpdmoney。 |
+
+| `assistant_cx_money` | NUMERIC(18,2) | | | 助教“次课/套餐/持续课”等另一类助教项目的金额。 | settlement_records - assistantcxmoney。 | settlement_records.json - $ - assistantcxmoney。 |
+
+| `adjust_amount` | NUMERIC(18,2) | | | 人工调价金额(总和),包括整单减免、特殊调整等。 | settlement_records - adjustamount。 | settlement_records.json - $ - adjustamount。 |
+
+| `pay_amount` | NUMERIC(18,2) | | | 本次结账“实付金额”(顾客实际支付的总金额),不包括券面值、积分等非现金部分。 | settlement_records - payamount。 | settlement_records.json - $ - payamount。 |
+
+| `balance_amount` | NUMERIC(18,2) | | | 从会员余额账户扣除的金额(储值卡余额消费)。 | settlement_records - balanceamount。 | settlement_records.json - $ - balanceamount。 |
+
+| `recharge_card_amount` | NUMERIC(18,2) | | | 与“充值卡”相关的支付额,可能表示本次使用充值卡抵扣的金额。 | settlement_records - rechargecardamount。 | settlement_records.json - $ - rechargecardamount。 |
+
+| `gift_card_amount` | NUMERIC(18,2) | | | 礼品卡/代金卡的支付金额。 | settlement_records - giftcardamount。 | settlement_records.json - $ - giftcardamount。 |
+
+| `coupon_amount` | NUMERIC(18,2) | | | 本单实际由优惠券(代金券/团购券等)抵扣的金额。 | settlement_records - couponamount。 | settlement_records.json - $ - couponamount。 |
+
+| `rounding_amount` | NUMERIC(18,2) | | | 抹零金额/舍入差值。如四舍五入或按角、分抹零产生的调整。 | settlement_records - roundingamount。 | settlement_records.json - $ - roundingamount。 |
+
+| `point_amount` | NUMERIC(18,2) | | | 代表与积分相关的一个金额或数量指标。结合字段命名,可能有两种用途:。 | settlement_records - pointamount。 | settlement_records.json - $ - pointamount。 |
+
+
+
+## `dwd_store_goods_sale`
+
+
+
+- 表说明:DWD 明细事实表:dwd_store_goods_sale。ODS 来源表:billiards_ods.store_goods_sales_records(对应 JSON:store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:store_goods_sale_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `store_goods_sale_id` | BIGINT | Y | | 本条「门店销售流水」记录的主键 ID;用于跨表关联与去重。 | store_goods_sales_records - id。 | store_goods_sales_records.json - data.orderGoodsLedgers - id。 |
+
+| `order_trade_no` | BIGINT | | | 订单交易号(业务单号)。 | store_goods_sales_records - order_trade_no。 | store_goods_sales_records.json - data.orderGoodsLedgers - order_trade_no。 |
+
+| `order_settle_id` | BIGINT | | dwd_settlement_head(order_settle_id) | 订单结算 ID(结账单主键);用于跨表关联与去重。 | store_goods_sales_records - order_settle_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - order_settle_id。 |
+
+| `order_pay_id` | BIGINT | | | 关联支付记录的 ID;用于跨表关联与去重。 | store_goods_sales_records - order_pay_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - order_pay_id。 |
+
+| `order_goods_id` | BIGINT | | | 订单商品明细 ID(订单内部的商品行主键);用于跨表关联与去重。 | store_goods_sales_records - order_goods_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - order_goods_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID(系统主键);用途:门店维度分组、计营业额、与门店档案关联。 | store_goods_sales_records - site_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - site_id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID;用途:多租户数据隔离与按租户汇总。 | store_goods_sales_records - tenant_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - tenant_id。 |
+
+| `site_goods_id` | BIGINT | | dim_store_goods(site_goods_id) | 门店商品 ID;用于跨表关联与去重。 | store_goods_sales_records - site_goods_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - site_goods_id。 |
+
+| `tenant_goods_id` | BIGINT | | dim_tenant_goods(tenant_goods_id) | 租户(品牌)级商品 ID(全局商品 ID);用于跨表关联与去重。 | store_goods_sales_records - tenant_goods_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_id。 |
+
+| `tenant_goods_category_id` | BIGINT | | | 租户级商品一级分类 ID;用于跨表关联与去重。 | store_goods_sales_records - tenant_goods_category_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_category_id。 |
+
+| `tenant_goods_business_id` | BIGINT | | | 租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度);用于跨表关联与去重。 | store_goods_sales_records - tenant_goods_business_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - tenant_goods_business_id。 |
+
+| `site_table_id` | BIGINT | | | 球台 ID;用于跨表关联与去重。 | store_goods_sales_records - site_table_id。 | store_goods_sales_records.json - data.orderGoodsLedgers - site_table_id。 |
+
+| `ledger_name` | VARCHAR(200) | | | 销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。 | store_goods_sales_records - ledger_name。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_name。 |
+
+| `ledger_group_name` | VARCHAR(100) | | | 销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。 | store_goods_sales_records - ledger_group_name。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_group_name。 |
+
+| `ledger_unit_price` | NUMERIC(18,2) | | | 商品在该次销售中的「结算单价」(元/单位)。 | store_goods_sales_records - ledger_unit_price。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_unit_price。 |
+
+| `ledger_count` | INTEGER | | | 销售数量(以 unit 为单位,unit 字段在门店商品档案中)。 | store_goods_sales_records - ledger_count。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_count。 |
+
+| `ledger_amount` | NUMERIC(18,2) | | | 原始应收金额,公式上接近 ledger_unit_price × ledger_count。 | store_goods_sales_records - ledger_amount。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_amount。 |
+
+| `discount_price` | NUMERIC(18,2) | | | 本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。 | store_goods_sales_records - discount_money。 | store_goods_sales_records.json - data.orderGoodsLedgers - discount_money。 |
+
+| `real_goods_money` | NUMERIC(18,2) | | | 商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。 | store_goods_sales_records - real_goods_money。 | store_goods_sales_records.json - data.orderGoodsLedgers - real_goods_money。 |
+
+| `cost_money` | NUMERIC(18,2) | | | 本条销售对应的成本金额(以元计)。 | store_goods_sales_records - cost_money。 | store_goods_sales_records.json - data.orderGoodsLedgers - cost_money。 |
+
+| `ledger_status` | INTEGER | | | 销售流水状态。 | store_goods_sales_records - ledger_status。 | store_goods_sales_records.json - data.orderGoodsLedgers - ledger_status。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志;软删除/作废标记,分析通常需过滤为有效记录。 | store_goods_sales_records - is_delete。 | store_goods_sales_records.json - data.orderGoodsLedgers - is_delete。 |
+
+| `create_time` | TIMESTAMPTZ | | | 销售记录创建时间,通常就是结账时间或录入时间;记录源系统创建时间,用于增量同步和口径对齐。 | store_goods_sales_records - create_time。 | store_goods_sales_records.json - data.orderGoodsLedgers - create_time。 |
+
+
+
+## `dwd_table_fee_adjust`
+
+
+
+- 表说明:DWD 明细事实表:dwd_table_fee_adjust。ODS 来源表:billiards_ods.table_fee_discount_records(对应 JSON:table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:table_fee_adjust_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `table_fee_adjust_id` | BIGINT | Y | | 台费打折 / 调整流水主键 ID。;用途:在“台费调账表”中唯一标识一条折扣/调账操作;用于跨表关联与去重。 | table_fee_discount_records - id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - id。 |
+
+| `order_trade_no` | BIGINT | | | 订单交易号。;关联:与 台费流水.json、助教流水.json、小票详情.json 中的同名字段一致,用于把这一条“台费调整”挂接到某笔订单上。 | table_fee_discount_records - order_trade_no。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - order_trade_no。 |
+
+| `order_settle_id` | BIGINT | | dwd_settlement_head(order_settle_id) | 结算单/小票 ID。;关联:与“小票详情.json”中的 orderSettleId 对应;用于跨表关联与去重。 | table_fee_discount_records - order_settle_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - order_settle_id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID。;用途:标识记录属于哪一个商户(同一个“非球科技”租户);用途:多租户数据隔离与按租户汇总。 | table_fee_discount_records - tenant_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,本批数据全部为同一家门店(朗朗桌球)。;关联:与 siteProfile.id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | table_fee_discount_records - site_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - site_id。 |
+
+| `table_id` | BIGINT | | dim_table(table_id) | 台桌 ID。;关联:与 台费流水.json 中的 site_table_id 一致;用于跨表关联与去重。 | table_fee_discount_records - site_table_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - site_table_id。 |
+
+| `table_area_id` | BIGINT | | | 租户维度的“台桌区域 ID”。;关联:与台桌区域配置表对应,帮助从区域维度分析打折分布(结构上可用);用于跨表关联与去重。 | table_fee_discount_records - tenant_table_area_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。 |
+
+| `table_area_name` | VARCHAR(64) | | | 名称字段,用于展示、检索与分组。 | table_fee_discount_records - tableprofile.table_area_name。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - tableprofile.table_area_name。 |
+
+| `tenant_table_area_id` | BIGINT | | | 租户维度的“台桌区域 ID”。;关联:与台桌区域配置表对应,帮助从区域维度分析打折分布(结构上可用);用于跨表关联与去重。 | table_fee_discount_records - tenant_table_area_id。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - tenant_table_area_id。 |
+
+| `ledger_amount` | NUMERIC(18,2) | | | 通过与 台费流水.json 做对比,可以明确:。 | table_fee_discount_records - ledger_amount。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_amount。 |
+
+| `ledger_status` | INTEGER | | | 业务状态/类型字段,用于过滤、分类与统计口径区分。 | table_fee_discount_records - ledger_status。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - ledger_status。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志:;软删除/作废标记,分析通常需过滤为有效记录。 | table_fee_discount_records - is_delete。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - is_delete。 |
+
+| `adjust_time` | TIMESTAMPTZ | | | 台费调整记录的创建时间,即打折操作被执行的时间戳。 | table_fee_discount_records - create_time。 | table_fee_discount_records.json - data.taiFeeAdjustInfos - create_time。 |
+
+
+
+## `dwd_table_fee_log`
+
+
+
+- 表说明:DWD 明细事实表:dwd_table_fee_log。ODS 来源表:billiards_ods.table_fee_transactions(对应 JSON:table_fee_transactions.json;分析:table_fee_transactions-Analysis.md)。装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。
+
+- 主键:table_fee_log_id
+
+- 类型:事实/明细
+
+
+
+| 字段 | 类型 | 主键 | 关联(推断) | 字段用途(说明) | ODS来源 | JSON字段 |
+
+|---|---|---:|---|---|---|---|
+
+| `table_fee_log_id` | BIGINT | Y | | 台费流水记录主键(事实表主键);用于跨表关联与去重。 | table_fee_transactions - id。 | table_fee_transactions.json - data.siteTableUseDetailsList - id。 |
+
+| `order_trade_no` | BIGINT | | | 订单交易号,是整笔订单的主编号。;关联:与其它 JSON(如 助教流水、小票详情、门店销售记录)中的同名字段一致,用于把 同一订单下的台费、助教、商品等多条明细串联。 | table_fee_transactions - order_trade_no。 | table_fee_transactions.json - data.siteTableUseDetailsList - order_trade_no。 |
+
+| `order_settle_id` | BIGINT | | dwd_settlement_head(order_settle_id) | 结算单号/结账 ID,对应一次结账操作。;关联:与“小票详情.json”中的 orderSettleId 对应;用于跨表关联与去重。 | table_fee_transactions - order_settle_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - order_settle_id。 |
+
+| `order_pay_id` | BIGINT | | | 订单支付记录 ID。;关联:对应“支付记录.json”中的 id 或 relate_id(视模型而定),用于追踪这条台费最终对应哪一条支付流水。 | table_fee_transactions - order_pay_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - order_pay_id。 |
+
+| `tenant_id` | BIGINT | | | 租户/品牌 ID。本文件所有记录都属于同一租户。;关联:与所有其它 JSON 中的 tenant_id 一致,用于跨表做“商户维度”的过滤。 | table_fee_transactions - tenant_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - tenant_id。 |
+
+| `site_id` | BIGINT | | dim_site(site_id) | 门店 ID,本次数据全部来自同一门店(朗朗桌球)。;关联:与 siteProfile.id 一致;用途:门店维度分组、计营业额、与门店档案关联。 | table_fee_transactions - site_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - site_id。 |
+
+| `site_table_id` | BIGINT | | | 球台 ID。;关联:对应“台桌列表”中的 id(当前导出文件中有一类与之对应的台桌配置表);用于跨表关联与去重。 | table_fee_transactions - site_table_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - site_table_id。 |
+
+| `site_table_area_id` | BIGINT | | | 门店内“台桌区域” ID(站在门店物理布局的角度)。;关联:对应“门店台桌区域配置表”的主键;用于跨表关联与去重。 | table_fee_transactions - site_table_area_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_id。 |
+
+| `site_table_area_name` | VARCHAR(64) | | | 台桌区域的名称,用于门店表现和区域统计。 | table_fee_transactions - site_table_area_name。 | table_fee_transactions.json - data.siteTableUseDetailsList - site_table_area_name。 |
+
+| `tenant_table_area_id` | BIGINT | | | 租户维度的台桌区域 ID(品牌层面的同一类区域)。;关联:对应租户层面的“区域维表”,支持多门店共享同一套区域配置;用于跨表关联与去重。 | table_fee_transactions - tenant_table_area_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - tenant_table_area_id。 |
+
+| `member_id` | BIGINT | | dim_member(member_id) | 门店/租户内的会员 ID。;关联:与“会员档案.json(tenantMemberInfos)”内的 id 对应(有部分 ID 完全匹配,部分会员可能不在当前导出页);用于跨表关联与去重。 | table_fee_transactions - member_id。 | table_fee_transactions.json - data.siteTableUseDetailsList - member_id。 |
+
+| `ledger_name` | VARCHAR(64) | | | 台号名称,实际展示给员工/顾客看的桌台编号。 | table_fee_transactions - ledger_name。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_name。 |
+
+| `ledger_unit_price` | NUMERIC(18,2) | | | 台费结算时设置的 每小时单价/计费单价。 | table_fee_transactions - ledger_unit_price。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_unit_price。 |
+
+| `ledger_count` | INTEGER | | | 台账记录的计费秒数,计费用秒数(应收时长)。 | table_fee_transactions - ledger_count。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_count。 |
+
+| `ledger_amount` | NUMERIC(18,2) | | | 按单价与计费时长计算出的原始应收台费金额。 | table_fee_transactions - ledger_amount。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_amount。 |
+
+| `real_table_charge_money` | NUMERIC(18,2) | | | 台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。 | table_fee_transactions - real_table_charge_money。 | table_fee_transactions.json - data.siteTableUseDetailsList - real_table_charge_money。 |
+
+| `coupon_promotion_amount` | NUMERIC(18,2) | | | 由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。 | table_fee_transactions - coupon_promotion_amount。 | table_fee_transactions.json - data.siteTableUseDetailsList - coupon_promotion_amount。 |
+
+| `member_discount_amount` | NUMERIC(18,2) | | | 由会员权益产生的优惠金额,例如会员折扣、会员价等。 | table_fee_transactions - member_discount_amount。 | table_fee_transactions.json - data.siteTableUseDetailsList - member_discount_amount。 |
+
+| `adjust_amount` | NUMERIC(18,2) | | | 调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。 | table_fee_transactions - adjust_amount。 | table_fee_transactions.json - data.siteTableUseDetailsList - adjust_amount。 |
+
+| `real_table_use_seconds` | INTEGER | | | 实际使用的总秒数(系统真实统计的使用时长)。 | table_fee_transactions - real_table_use_seconds。 | table_fee_transactions.json - data.siteTableUseDetailsList - real_table_use_seconds。 |
+
+| `add_clock_seconds` | INTEGER | | | 加钟秒数,在原有使用基础上追加的时长。 | table_fee_transactions - add_clock_seconds。 | table_fee_transactions.json - data.siteTableUseDetailsList - add_clock_seconds。 |
+
+| `start_use_time` | TIMESTAMPTZ | | | 台开始使用的时间(实际开台时间)。 | table_fee_transactions - start_use_time。 | table_fee_transactions.json - data.siteTableUseDetailsList - start_use_time。 |
+
+| `ledger_end_time` | TIMESTAMPTZ | | | 台账上的计费结束时间。 | table_fee_transactions - ledger_end_time。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_end_time。 |
+
+| `create_time` | TIMESTAMPTZ | | | 这条台费流水记录的创建时间,通常接近结账时间;记录源系统创建时间,用于增量同步和口径对齐。 | table_fee_transactions - create_time。 | table_fee_transactions.json - data.siteTableUseDetailsList - create_time。 |
+
+| `ledger_status` | INTEGER | | | 1:正常已结算台费。 | table_fee_transactions - ledger_status。 | table_fee_transactions.json - data.siteTableUseDetailsList - ledger_status。 |
+
+| `is_single_order` | INTEGER | | | 1:该台费记录对应的是一个独立计费单元(单独结算的桌费)。 | table_fee_transactions - is_single_order。 | table_fee_transactions.json - data.siteTableUseDetailsList - is_single_order。 |
+
+| `is_delete` | INTEGER | | | 逻辑删除标志:;软删除/作废标记,分析通常需过滤为有效记录。 | table_fee_transactions - is_delete。 | table_fee_transactions.json - data.siteTableUseDetailsList - is_delete。 |
+
+
+
+---
+
+生成时间:2025-12-15 19:35:55
+
diff --git a/etl_billiards/docs/table_2025-12-19/_generate_assistant_tables.py b/etl_billiards/docs/table_2025-12-19/_generate_assistant_tables.py
new file mode 100644
index 0000000..93301b6
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/_generate_assistant_tables.py
@@ -0,0 +1,585 @@
+# -*- coding: utf-8 -*-
+"""生成 2025年10-12月 助教排行榜 + 助教详情表(CSV + MD)。
+
+输出目录:etl_billiards/docs/table_2025-12-19
+
+注意:客户流水/充值归因涉及“多助教/多订单命中”时按全额复制计入,会导致助教汇总>门店汇总,表格说明会写明。
+"""
+
+from __future__ import annotations
+
+import csv
+import re
+from dataclasses import dataclass
+from decimal import Decimal
+from pathlib import Path
+from statistics import median
+from typing import Any
+
+import psycopg2
+import psycopg2.extras
+
+
+SITE_ID = 2790685415443269
+TZ = "Asia/Shanghai"
+
+WIN_OCT = ("2025-10-01 00:00:00+08", "2025-11-01 00:00:00+08")
+WIN_NOV = ("2025-11-01 00:00:00+08", "2025-12-01 00:00:00+08")
+WIN_DEC = ("2025-12-01 00:00:00+08", "2026-01-01 00:00:00+08")
+WIN_ALL = (WIN_OCT[0], WIN_DEC[1])
+
+MONTHS = [
+ ("2025-10", "10月", WIN_OCT),
+ ("2025-11", "11月", WIN_NOV),
+ ("2025-12", "12月", WIN_DEC),
+]
+
+REPO_ROOT = Path(__file__).resolve().parents[3]
+ENV_PATH = REPO_ROOT / "etl_billiards" / ".env"
+OUT_DIR = Path(__file__).resolve().parent
+
+
+@dataclass(frozen=True)
+class SqlBlock:
+ title: str
+ sql: str
+
+
+def read_pg_dsn() -> str:
+ text = ENV_PATH.read_text(encoding="utf-8")
+ m = re.search(r"^PG_DSN=(.+)$", text, re.M)
+ if not m:
+ raise RuntimeError(f"未在 {ENV_PATH} 中找到 PG_DSN")
+ return m.group(1).strip()
+
+
+def conn():
+ return psycopg2.connect(read_pg_dsn(), connect_timeout=10)
+
+
+def sanitize_filename(name: str) -> str:
+ name = name.strip()
+ name = re.sub(r"[<>:\"/\\|?*]+", "_", name)
+ name = re.sub(r"\s+", " ", name)
+ return name
+
+
+def d(v: Any) -> Decimal:
+ if v is None:
+ return Decimal("0")
+ if isinstance(v, Decimal):
+ return v
+ return Decimal(str(v))
+
+
+def fmt_money(v: Any) -> str:
+ return f"{d(v):.2f}"
+
+
+def fmt_hours(v: Any, digits: int = 2) -> str:
+ q = Decimal("1").scaleb(-digits)
+ return f"{d(v).quantize(q):f}h"
+
+
+def write_csv(path: Path, title: str, description: str, header_rows: list[list[str]], rows: list[list[Any]]) -> None:
+ path.parent.mkdir(parents=True, exist_ok=True)
+ with path.open("w", newline="", encoding="utf-8") as f:
+ w = csv.writer(f)
+ w.writerow([title])
+ w.writerow([description])
+ w.writerow([])
+ for hr in header_rows:
+ w.writerow(hr)
+ for r in rows:
+ w.writerow(["" if v is None else v for v in r])
+
+
+def write_csv_sections(path: Path, title: str, description: str, section_rows: list[list[Any]]) -> None:
+ path.parent.mkdir(parents=True, exist_ok=True)
+ with path.open("w", newline="", encoding="utf-8") as f:
+ w = csv.writer(f)
+ w.writerow([title])
+ w.writerow([description])
+ w.writerow([])
+ for r in section_rows:
+ w.writerow(["" if v is None else v for v in r])
+
+
+def write_md(path: Path, title: str, thinking: str, description: str, sql_blocks: list[SqlBlock]) -> None:
+ parts: list[str] = []
+ parts.append(f"# {title}\n")
+ parts.append("## 思考过程\n")
+ parts.append(thinking.strip() + "\n")
+ parts.append("\n## 查询说明\n")
+ parts.append(description.strip() + "\n")
+ parts.append("\n## SQL\n")
+ for b in sql_blocks:
+ parts.append(f"\n### {b.title}\n")
+ parts.append("```sql\n")
+ parts.append(b.sql.strip() + "\n")
+ parts.append("```\n")
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text("".join(parts), encoding="utf-8")
+
+
+def fetch_all(cur, sql: str, params: dict[str, Any]) -> list[dict[str, Any]]:
+ cur.execute(sql, params)
+ return list(cur.fetchall())
+
+
+def month_case(ts_expr: str) -> str:
+ parts = []
+ for month_key, _, (ws, we) in MONTHS:
+ parts.append(
+ f"when {ts_expr} >= '{ws}'::timestamptz and {ts_expr} < '{we}'::timestamptz then '{month_key}'"
+ )
+ return "case " + " ".join(parts) + " else null end"
+
+
+def sql_order_base(window_start: str, window_end: str) -> str:
+ return f"""
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '{window_start}'::timestamptz
+ and tfl.start_use_time < '{window_end}'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+"""
+
+
+def dense_rank_desc(values: dict[str, Decimal]) -> dict[str, int]:
+ uniq = sorted({v for v in values.values() if v > 0}, reverse=True)
+ rank_map = {v: i + 1 for i, v in enumerate(uniq)}
+ return {k: rank_map.get(v, 0) for k, v in values.items()}
+
+
+def calc_diff(all_values: dict[str, Decimal], current: Decimal) -> tuple[Decimal, Decimal]:
+ xs = [v for v in all_values.values() if v > 0]
+ if not xs or current <= 0:
+ return Decimal("0"), Decimal("0")
+ avg = sum(xs) / Decimal(len(xs))
+ med = Decimal(str(median([float(v) for v in xs])))
+ return current - avg, current - med
+
+
+def main() -> None:
+ OUT_DIR.mkdir(parents=True, exist_ok=True)
+
+ with conn() as c, c.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
+ assistants_rows = fetch_all(
+ cur,
+ """
+select distinct nickname as assistant
+from billiards_dwd.dwd_assistant_service_log
+where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+order by assistant;
+""",
+ {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]},
+ )
+ assistants = [r["assistant"] for r in assistants_rows if r.get("assistant")]
+
+ # 助教-客户-月份:服务时长
+ sql_svc = f"""
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ {month_case('asl.start_use_time')} as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+"""
+ svc_rows = fetch_all(cur, sql_svc, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]})
+
+ # 助教-客户-月份:客户流水
+ sql_rev = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ {month_case('o.order_start_time')} as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+"""
+ rev_rows = fetch_all(cur, sql_rev, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]})
+
+ # 助教-客户-月份:充值归因
+ sql_rech = f"""
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ {month_case('m.pay_time')} as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+"""
+ rech_rows = fetch_all(cur, sql_rech, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]})
+
+ # 汇总:月度助教指标
+ svc_map = {mk: {a: {"base": Decimal('0'), "extra": Decimal('0')} for a in assistants} for mk,_,_ in MONTHS}
+ for r in svc_rows:
+ mk = r["month_key"]; a = r["assistant"]
+ if mk in svc_map and a in svc_map[mk]:
+ svc_map[mk][a]["base"] += d(r["base_hours"])
+ svc_map[mk][a]["extra"] += d(r["extra_hours"])
+
+ revenue_map = {mk: {a: Decimal('0') for a in assistants} for mk,_,_ in MONTHS}
+ for r in rev_rows:
+ mk = r["month_key"]; a = r["assistant"]
+ if mk in revenue_map and a in revenue_map[mk]:
+ revenue_map[mk][a] += d(r["revenue_amount"])
+
+ recharge_map = {mk: {a: Decimal('0') for a in assistants} for mk,_,_ in MONTHS}
+ for r in rech_rows:
+ mk = r["month_key"]; a = r["assistant"]
+ if mk in recharge_map and a in recharge_map[mk]:
+ recharge_map[mk][a] += d(r["recharge_amount"])
+
+ # ====== 输出4张排行榜 ======
+ def write_rank(file_stem: str, title: str, desc: str, rows: list[list[Any]]):
+ write_csv(OUT_DIR / f"{file_stem}.csv", title, desc, [["月份", "排名", "助教昵称", "指标"]], rows)
+ write_md(OUT_DIR / f"{file_stem}.md", title, "按月聚合并做dense_rank排名。", desc, [])
+
+ rows = []
+ for mk,_,_ in MONTHS:
+ values = {a: svc_map[mk][a]["base"] for a in assistants}
+ ranks = dense_rank_desc(values)
+ for a in sorted(assistants, key=lambda x: (ranks[x] if ranks[x] else 999999, x)):
+ v = values[a]
+ if v > 0:
+ rows.append([mk, ranks[a], a, fmt_hours(v, 2)])
+ write_rank(
+ "助教_基础课时长排行_2025年10-12月",
+ "2025年10-12月 助教基础课时长排行榜",
+ "口径:order_assistant_type=1,时长=income_seconds/3600(小时),按月排名。",
+ rows,
+ )
+
+ rows = []
+ for mk,_,_ in MONTHS:
+ values = {a: svc_map[mk][a]["extra"] for a in assistants}
+ ranks = dense_rank_desc(values)
+ for a in sorted(assistants, key=lambda x: (ranks[x] if ranks[x] else 999999, x)):
+ v = values[a]
+ if v > 0:
+ rows.append([mk, ranks[a], a, fmt_hours(v, 2)])
+ write_rank(
+ "助教_附加课时长排行_2025年10-12月",
+ "2025年10-12月 助教附加课(超休)时长排行榜",
+ "口径:order_assistant_type=2,超休时长=income_seconds/3600(小时),按月排名。",
+ rows,
+ )
+
+ rows = []
+ for mk,_,_ in MONTHS:
+ values = revenue_map[mk]
+ ranks = dense_rank_desc(values)
+ for a in sorted(assistants, key=lambda x: (ranks[x] if ranks[x] else 999999, x)):
+ v = values[a]
+ if v > 0:
+ rows.append([mk, ranks[a], a, fmt_money(v)])
+ write_rank(
+ "助教_客户流水排行_2025年10-12月",
+ "2025年10-12月 助教客户流水排行榜(全额复制口径)",
+ "口径:客户流水=台费+助教+商品应付金额按订单归集后,全额计入订单内每位助教;多助教会导致汇总>门店总额。",
+ rows,
+ )
+
+ rows = []
+ for mk,_,_ in MONTHS:
+ values = recharge_map[mk]
+ ranks = dense_rank_desc(values)
+ for a in sorted(assistants, key=lambda x: (ranks[x] if ranks[x] else 999999, x)):
+ v = values[a]
+ if v > 0:
+ rows.append([mk, ranks[a], a, fmt_money(v)])
+ write_rank(
+ "助教_客户充值归因排行_2025年10-12月",
+ "2025年10-12月 助教客户充值归因排行榜(全额复制口径)",
+ "口径:充值支付(dwd_payment.relate_type=5)在消费窗口±30分钟内命中且订单有助教,则全额计入助教;多助教/多订单命中会重复计入。",
+ rows,
+ )
+
+ # ====== 输出助教详情(每人一份) ======
+ # 会员昵称
+ cur.execute("select member_id, nickname from billiards_dwd.dim_member where scd2_is_current=1")
+ member_name = {r["member_id"]: (r.get("nickname") or "") for r in cur.fetchall()}
+
+ # 索引:assistant->member->month
+ svc_idx = {a: {} for a in assistants}
+ for r in svc_rows:
+ a = r["assistant"]; mid = int(r["member_id"]); mk = r["month_key"]
+ svc_idx.setdefault(a, {}).setdefault(mid, {})[mk] = {"base": d(r["base_hours"]), "extra": d(r["extra_hours"])}
+
+ rev_idx = {a: {} for a in assistants}
+ for r in rev_rows:
+ a = r["assistant"]; mid = int(r["member_id"]); mk = r["month_key"]
+ rev_idx.setdefault(a, {}).setdefault(mid, {})[mk] = d(r["revenue_amount"])
+
+ rech_idx = {a: {} for a in assistants}
+ for r in rech_rows:
+ a = r["assistant"]; mid = int(r["member_id"]); mk = r["month_key"]
+ rech_idx.setdefault(a, {}).setdefault(mid, {})[mk] = d(r["recharge_amount"])
+
+ for a in assistants:
+ safe = sanitize_filename(a)
+ csv_path = OUT_DIR / f"助教详情_{safe}.csv"
+ md_path = OUT_DIR / f"助教详情_{safe}.md"
+
+ # 评价(简短)
+ base_total = sum((svc_map[mk][a]["base"] for mk,_,_ in MONTHS), Decimal('0'))
+ extra_total = sum((svc_map[mk][a]["extra"] for mk,_,_ in MONTHS), Decimal('0'))
+ rev_total = sum((revenue_map[mk][a] for mk,_,_ in MONTHS), Decimal('0'))
+ rech_total = sum((recharge_map[mk][a] for mk,_,_ in MONTHS), Decimal('0'))
+
+ # 头部客户 Top100(按12月消费业绩)
+ members = set(rev_idx.get(a, {}).keys()) | set(svc_idx.get(a, {}).keys()) | set(rech_idx.get(a, {}).keys())
+ def rev_dec(mid: int) -> Decimal:
+ return rev_idx.get(a, {}).get(mid, {}).get('2025-12', Decimal('0'))
+ top_members = sorted(members, key=lambda mid: rev_dec(mid), reverse=True)[:100]
+
+ top3 = '、'.join([(member_name.get(mid) or str(mid)) for mid in top_members[:3]])
+ assistant_review = (
+ f"评价:基础{fmt_hours(base_total,1)},附加{fmt_hours(extra_total,1)};"
+ f"客户流水¥{rev_total:.2f},充值归因¥{rech_total:.2f};"
+ f"头部客户(12月)Top3:{top3 or '无'}。"
+ )
+
+ # Part1-4
+ part1=[]; part2=[]; part3=[]; part4=[]
+ for mk, mcn, _ in MONTHS:
+ base_v = svc_map[mk][a]["base"]
+ extra_v = svc_map[mk][a]["extra"]
+ rev_v = revenue_map[mk][a]
+ rech_v = recharge_map[mk][a]
+
+ base_all = {x: svc_map[mk][x]["base"] for x in assistants}
+ extra_all = {x: svc_map[mk][x]["extra"] for x in assistants}
+ rev_all = {x: revenue_map[mk][x] for x in assistants}
+ rech_all = {x: recharge_map[mk][x] for x in assistants}
+
+ base_rank = dense_rank_desc(base_all).get(a, 0)
+ extra_rank = dense_rank_desc(extra_all).get(a, 0)
+ rev_rank = dense_rank_desc(rev_all).get(a, 0)
+ rech_rank = dense_rank_desc(rech_all).get(a, 0)
+
+ base_da, base_dm = calc_diff(base_all, base_v)
+ extra_da, extra_dm = calc_diff(extra_all, extra_v)
+ rev_da, rev_dm = calc_diff(rev_all, rev_v)
+ rech_da, rech_dm = calc_diff(rech_all, rech_v)
+
+ part1.append([mcn, fmt_hours(base_v,2), base_rank or "", fmt_hours(base_da,2), fmt_hours(base_dm,2)])
+ part2.append([mcn, fmt_hours(extra_v,2), extra_rank or "", fmt_hours(extra_da,2), fmt_hours(extra_dm,2)])
+ part3.append([mcn, fmt_money(rev_v), rev_rank or "", fmt_money(rev_da), fmt_money(rev_dm)])
+ part4.append([mcn, fmt_money(rech_v), rech_rank or "", fmt_money(rech_da), fmt_money(rech_dm)])
+
+ # Part5 rows
+ part5=[]
+ for i, mid in enumerate(top_members, start=1):
+ def h_pair(month_key: str) -> str:
+ v = svc_idx.get(a, {}).get(mid, {}).get(month_key, {})
+ return f"{fmt_hours(v.get('base',Decimal('0')),1)} / {fmt_hours(v.get('extra',Decimal('0')),1)}"
+ def rev_m(month_key: str) -> Decimal:
+ return rev_idx.get(a, {}).get(mid, {}).get(month_key, Decimal('0'))
+ def rech_m(month_key: str) -> Decimal:
+ return rech_idx.get(a, {}).get(mid, {}).get(month_key, Decimal('0'))
+ name = member_name.get(mid) or str(mid)
+ part5.append([
+ i,
+ name,
+ h_pair('2025-12'), fmt_money(rev_m('2025-12')), fmt_money(rech_m('2025-12')),
+ h_pair('2025-11'), fmt_money(rev_m('2025-11')), fmt_money(rech_m('2025-11')),
+ h_pair('2025-10'), fmt_money(rev_m('2025-10')), fmt_money(rech_m('2025-10')),
+ ])
+
+ title = f"助教详情:{a}(2025年10-12月)"
+ desc = (
+ "本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。"
+ "均值/中位数差值对比集合为当月该指标>0的助教。"
+ "充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。"
+ )
+
+ rows=[]
+ rows += [["一、基础课业绩"], ["说明:" + assistant_review], []]
+ rows += [["月份", "基础课业绩", "基础课业绩", "基础课业绩", "基础课业绩"], ["月份", "小时数", "排名", "平均值差值小时数", "中位数值差值小时数"]]
+ rows += part1
+ rows += [[], ["二、附加课业绩"], ["说明:附加课=order_assistant_type=2。"], []]
+ rows += [["月份", "附加课业绩", "附加课业绩", "附加课业绩", "附加课业绩"], ["月份", "小时数", "排名", "平均值差值小时数", "中位数值差值小时数"]]
+ rows += part2
+ rows += [[], ["三、客户消费业绩"], ["说明:订单台费+助教+商品应付金额全额计入订单内助教。"], []]
+ rows += [["月份", "客户消费业绩", "客户消费业绩", "客户消费业绩", "客户消费业绩"], ["月份", "合计元", "排名", "平均值差值元", "中位数值差值元"]]
+ rows += part3
+ rows += [[], ["四、客户充值业绩"], ["说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。"], []]
+ rows += [["月份", "客户充值业绩", "客户充值业绩", "客户充值业绩", "客户充值业绩"], ["月份", "合计元", "排名", "平均值差值元", "中位数值差值元"]]
+ rows += part4
+ rows += [[], ["五、头部客户(按12月消费业绩排序,Top100)"], ["说明:基础/附加课时=基础h/附加h。"], []]
+ rows += [["排名", "客户名称", "12月", "12月", "12月", "11月", "11月", "11月", "10月", "10月", "10月"],
+ ["排名", "客户名称", "基础/附加课时", "消费业绩(元)", "客户充值(元)", "基础/附加课时", "消费业绩(元)", "客户充值(元)", "基础/附加课时", "消费业绩(元)", "客户充值(元)"]]
+ rows += part5
+
+ write_csv_sections(csv_path, title, desc, rows)
+ write_md(
+ md_path,
+ title,
+ "按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。",
+ desc + "\n" + assistant_review,
+ [
+ SqlBlock("服务时长(助教-客户-月份)", sql_svc),
+ SqlBlock("客户流水(助教-客户-月份)", sql_rev),
+ SqlBlock("充值归因(助教-客户-月份)", sql_rech),
+ ],
+ )
+
+ print(f"完成:{OUT_DIR}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/etl_billiards/docs/table_2025-12-19/_generate_tables.py b/etl_billiards/docs/table_2025-12-19/_generate_tables.py
new file mode 100644
index 0000000..5bcbf63
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/_generate_tables.py
@@ -0,0 +1,1087 @@
+# -*- coding: utf-8 -*-
+"""生成 2025年10-12月 报表(CSV + MD)。
+
+输出目录:etl_billiards/docs/table_2025-12-19
+
+重要口径(已按需求固化):
+- 门店:site_id=2790685415443269
+- 月份切割:北京时间(+08)当月1日 00:00:00
+- 消费/流水:应付金额(不扣优惠),= 台费(dwd_table_fee_log.ledger_amount) + 助教(dwd_assistant_service_log.ledger_amount) + 商品(dwd_store_goods_sale.ledger_amount)
+- 助教时长:income_seconds(计费秒数)换算小时
+- 优惠:台费调账 dwd_table_fee_adjust.ledger_amount + 会员折扣 dwd_table_fee_log.member_discount_amount
+- 多助教/充值归因:全额复制计入(会导致汇总>门店总额),在表格说明中提示
+"""
+
+from __future__ import annotations
+
+import csv
+import re
+from dataclasses import dataclass
+from decimal import Decimal
+from pathlib import Path
+from typing import Any
+
+import psycopg2
+import psycopg2.extras
+
+
+SITE_ID = 2790685415443269
+TZ = "Asia/Shanghai"
+
+WIN_OCT = ("2025-10-01 00:00:00+08", "2025-11-01 00:00:00+08")
+WIN_NOV = ("2025-11-01 00:00:00+08", "2025-12-01 00:00:00+08")
+WIN_DEC = ("2025-12-01 00:00:00+08", "2026-01-01 00:00:00+08")
+WIN_ALL = (WIN_OCT[0], WIN_DEC[1])
+
+MONTHS = [
+ ("2025-10", "10月", WIN_OCT),
+ ("2025-11", "11月", WIN_NOV),
+ ("2025-12", "12月", WIN_DEC),
+]
+
+REPO_ROOT = Path(__file__).resolve().parents[3]
+ENV_PATH = REPO_ROOT / "etl_billiards" / ".env"
+OUT_DIR = Path(__file__).resolve().parent
+
+
+@dataclass(frozen=True)
+class SqlBlock:
+ title: str
+ sql: str
+
+
+def read_pg_dsn() -> str:
+ text = ENV_PATH.read_text(encoding="utf-8")
+ m = re.search(r"^PG_DSN=(.+)$", text, re.M)
+ if not m:
+ raise RuntimeError(f"未在 {ENV_PATH} 中找到 PG_DSN")
+ return m.group(1).strip()
+
+
+def conn():
+ return psycopg2.connect(read_pg_dsn(), connect_timeout=10)
+
+
+def sanitize_filename(name: str) -> str:
+ name = name.strip()
+ name = re.sub(r"[<>:\"/\\|?*]+", "_", name)
+ name = re.sub(r"\s+", " ", name)
+ return name
+
+
+def mask_phone(phone: str | None) -> str:
+ if not phone:
+ return ""
+ digits = re.sub(r"\D", "", phone)
+ if len(digits) < 7:
+ return phone
+ return re.sub(r"^(\d{3})\d{4}(\d+)$", r"\1****\2", digits)
+
+
+def d(v: Any) -> Decimal:
+ if v is None:
+ return Decimal("0")
+ if isinstance(v, Decimal):
+ return v
+ return Decimal(str(v))
+
+
+def fmt_money(v: Any) -> str:
+ return f"{d(v):.2f}"
+
+
+def fmt_hours(v: Any, digits: int = 1) -> str:
+ q = Decimal("1").scaleb(-digits)
+ return f"{d(v).quantize(q):f}h"
+
+
+def write_csv(path: Path, title: str, description: str, header_rows: list[list[str]], rows: list[list[Any]]) -> None:
+ path.parent.mkdir(parents=True, exist_ok=True)
+ with path.open("w", newline="", encoding="utf-8") as f:
+ w = csv.writer(f)
+ w.writerow([title])
+ w.writerow([description])
+ w.writerow([]) # 说明与表头之间空 1 行
+ for hr in header_rows:
+ w.writerow(hr)
+ for r in rows:
+ w.writerow(["" if v is None else v for v in r])
+
+
+def write_md(path: Path, title: str, thinking: str, description: str, sql_blocks: list[SqlBlock]) -> None:
+ parts: list[str] = []
+ parts.append(f"# {title}\n")
+ parts.append("## 思考过程\n")
+ parts.append(thinking.strip() + "\n")
+ parts.append("\n## 查询说明\n")
+ parts.append(description.strip() + "\n")
+ parts.append("\n## SQL\n")
+ for b in sql_blocks:
+ parts.append(f"\n### {b.title}\n")
+ parts.append("```sql\n")
+ parts.append(b.sql.strip() + "\n")
+ parts.append("```\n")
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text("".join(parts), encoding="utf-8")
+
+
+def fetch_all(cur, sql: str, params: dict[str, Any]) -> list[dict[str, Any]]:
+ cur.execute(sql, params)
+ return list(cur.fetchall())
+
+
+def month_case(ts_expr: str) -> str:
+ parts = []
+ for month_key, _, (ws, we) in MONTHS:
+ parts.append(
+ f"when {ts_expr} >= '{ws}'::timestamptz and {ts_expr} < '{we}'::timestamptz then '{month_key}'"
+ )
+ return "case " + " ".join(parts) + " else null end"
+
+
+def sql_order_base(window_start: str, window_end: str) -> str:
+ return f"""
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '{window_start}'::timestamptz
+ and tfl.start_use_time < '{window_end}'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+"""
+
+
+def build_finance_discount(cur) -> None:
+ title = "2025年10-12月 财务优惠(会员折扣+台费调账)分布"
+ desc = (
+ "优惠=会员折扣(dwd_table_fee_log.member_discount_amount)+台费调账(dwd_table_fee_adjust.ledger_amount),"
+ "按订单归集后汇总到客户(member_id),按订单最早开台时间切月;不含团购抵扣等其它优惠。"
+ )
+ thinking = "用台费订单为基准关联调账表,再按客户+月份汇总,输出“谁享受了优惠”及金额分布。"
+
+ sql = f"""
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ sum(tfl.member_discount_amount) as member_discount_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+adjusts as (
+ select
+ tfa.order_settle_id,
+ sum(tfa.ledger_amount) as adjust_amount
+ from billiards_dwd.dwd_table_fee_adjust tfa
+ join base_orders bo on bo.order_settle_id = tfa.order_settle_id
+ where tfa.site_id = %(site_id)s
+ and coalesce(tfa.is_delete,0) = 0
+ group by tfa.order_settle_id
+)
+, x as (
+ select
+ bo.member_id,
+ {month_case('bo.order_start_time')} as month_key,
+ coalesce(bo.member_discount_amount,0) as member_discount_amount,
+ coalesce(a.adjust_amount,0) as adjust_amount
+ from base_orders bo
+ left join adjusts a on a.order_settle_id = bo.order_settle_id
+)
+select
+ member_id,
+ month_key,
+ sum(member_discount_amount) as member_discount_sum,
+ sum(adjust_amount) as adjust_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+"""
+
+ rows = fetch_all(
+ cur,
+ sql,
+ {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]},
+ )
+
+ member_ids = sorted({r["member_id"] for r in rows if r["member_id"] not in (None, 0)})
+ cur.execute(
+ """
+select member_id, nickname, mobile, member_card_grade_name
+from billiards_dwd.dim_member
+where scd2_is_current=1 and member_id = any(%(ids)s)
+""",
+ {"ids": member_ids},
+ )
+ member_map = {r["member_id"]: {"name": (r.get("nickname") or ""), "mobile": (r.get("mobile") or ""), "vip": (r.get("member_card_grade_name") or "")} for r in cur.fetchall()}
+
+ per_member: dict[int, dict[str, Decimal]] = {}
+ for r in rows:
+ mid = r["member_id"]
+ if not mid or mid == 0:
+ continue
+ per_member.setdefault(mid, {})
+ mk = r["month_key"]
+ per_member[mid][f"{mk}_member"] = d(r["member_discount_sum"])
+ per_member[mid][f"{mk}_adjust"] = d(r["adjust_sum"])
+
+ out_rows: list[list[Any]] = []
+ for mid, info_d in per_member.items():
+ info = member_map.get(mid, {"name": "", "mobile": "", "vip": ""})
+ row: list[Any] = [info["name"], mask_phone(info["mobile"]), info["vip"]]
+ total = Decimal("0")
+ for mk, _, _ in MONTHS:
+ md = info_d.get(f"{mk}_member", Decimal("0"))
+ ad = info_d.get(f"{mk}_adjust", Decimal("0"))
+ row += [fmt_money(md), fmt_money(ad), fmt_money(md + ad)]
+ total += md + ad
+ row.append(fmt_money(total))
+ out_rows.append(row)
+
+ out_rows.sort(key=lambda r: Decimal(r[-1]), reverse=True)
+
+ csv_path = OUT_DIR / "财务_优惠分布_2025年10-12月.csv"
+ md_path = OUT_DIR / "财务_优惠分布_2025年10-12月.md"
+
+ write_csv(
+ csv_path,
+ title,
+ desc,
+ [
+ [
+ "客户名称",
+ "手机号(脱敏)",
+ "VIP卡/等级",
+ "10月",
+ "10月",
+ "10月",
+ "11月",
+ "11月",
+ "11月",
+ "12月",
+ "12月",
+ "12月",
+ "10-12月",
+ ],
+ [
+ "客户名称",
+ "手机号(脱敏)",
+ "VIP卡/等级",
+ "会员折扣(元)",
+ "台费调账(元)",
+ "合计优惠(元)",
+ "会员折扣(元)",
+ "台费调账(元)",
+ "合计优惠(元)",
+ "会员折扣(元)",
+ "台费调账(元)",
+ "合计优惠(元)",
+ "合计优惠(元)",
+ ],
+ ],
+ out_rows,
+ )
+
+ write_md(md_path, title, thinking, desc, [SqlBlock("优惠分布(客户+月份)", sql)])
+
+
+def build_customer_top100(cur) -> list[int]:
+ title_total = "2025年10-12月 客户消费能力Top100(总表)"
+ title_split = "2025年10-12月 客户消费能力Top100(分表)"
+
+ desc_total = (
+ "消费=台费(dwd_table_fee_log.ledger_amount)+助教(dwd_assistant_service_log.ledger_amount)+商品(dwd_store_goods_sale.ledger_amount),均为应付金额(不扣优惠),以台费订单为基准串联;"
+ "充值=充值支付流水(dwd_payment.relate_type=5, pay_status=2, pay_amount>0)按支付时间切月;"
+ "储值卡未使用金额=当前有效储值卡余额之和(dim_member_card_account.balance, member_card_type_name='储值卡');"
+ "喜爱助教=基础课时长+附加课时长*1.5(income_seconds换算小时),总表按10-12月汇总Top5。"
+ )
+ desc_split = "与总表同口径;分表仅计算12月喜爱助教Top5,并展示10-12月各月消费/充值。"
+
+ thinking = (
+ "以台费订单为基准汇总三类明细,满足应付金额口径,并输出Top100客户的消费/充值/助教偏好。"
+ "按你的要求,先生成评价为空的版本,再在脚本末尾回填评价。"
+ )
+
+ sql_top100 = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + """
+select
+ o.member_id,
+ sum(o.order_amount) as consume_total,
+ count(*) as order_cnt
+from orders o
+where o.member_id is not null and o.member_id <> 0
+group by o.member_id
+order by consume_total desc
+limit 100;
+"""
+
+ sql_monthly_consume = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+, x as (
+ select
+ o.member_id,
+ {month_case('o.order_start_time')} as month_key,
+ o.order_amount
+ from orders o
+ where o.member_id is not null and o.member_id <> 0
+)
+select
+ member_id,
+ month_key,
+ sum(order_amount) as consume_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+"""
+
+ sql_monthly_recharge = f"""
+with pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id = p.relate_id
+ where p.site_id = %(site_id)s
+ and p.relate_type = 5
+ and p.pay_status = 2
+ and p.pay_amount > 0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+)
+, x as (
+ select
+ member_id,
+ {month_case('pay_time')} as month_key,
+ pay_amount
+ from pay
+)
+select
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+"""
+
+ sql_fav_all = f"""
+with x as (
+ select
+ asl.tenant_member_id as member_id,
+ asl.nickname as assistant_nickname,
+ sum(case when asl.order_assistant_type=1 then asl.income_seconds else asl.income_seconds*1.5 end) / 3600.0 as weighted_hours
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.tenant_member_id is not null and asl.tenant_member_id <> 0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ group by asl.tenant_member_id, asl.nickname
+),
+ranked as (
+ select *, row_number() over(partition by member_id order by weighted_hours desc) as rn
+ from x
+)
+select
+ member_id,
+ string_agg(assistant_nickname || '(' || to_char(round(weighted_hours::numeric, 1), 'FM999999990.0') || 'h)', '、' order by weighted_hours desc) as fav5
+from ranked
+where rn <= 5
+group by member_id;
+"""
+
+ sql_stored_value = """
+select
+ tenant_member_id as member_id,
+ sum(balance) as stored_value_balance
+from billiards_dwd.dim_member_card_account
+where scd2_is_current=1
+ and coalesce(is_delete,0)=0
+ and member_card_type_name='储值卡'
+ and tenant_member_id = any(%(ids)s)
+group by tenant_member_id;
+"""
+
+ # 评价字段:画像查询(仅用于生成评价文本,不影响Top100口径)
+ sql_review_profile = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+select
+ o.member_id,
+ count(*) as orders,
+ avg(o.order_amount) as avg_order,
+ sum(o.table_use_seconds)/3600.0 as play_hours,
+ avg(o.table_use_seconds)/3600.0 as avg_play_hours,
+ min((o.order_start_time at time zone '{TZ}')::date) as first_visit_day,
+ max((o.order_start_time at time zone '{TZ}')::date) as last_visit_day,
+ count(distinct (o.order_start_time at time zone '{TZ}')::date) as visit_days,
+ sum(case when o.order_start_time >= '{WIN_OCT[0]}'::timestamptz and o.order_start_time < '{WIN_OCT[1]}'::timestamptz then 1 else 0 end) as orders_oct,
+ sum(case when o.order_start_time >= '{WIN_NOV[0]}'::timestamptz and o.order_start_time < '{WIN_NOV[1]}'::timestamptz then 1 else 0 end) as orders_nov,
+ sum(case when o.order_start_time >= '{WIN_DEC[0]}'::timestamptz and o.order_start_time < '{WIN_DEC[1]}'::timestamptz then 1 else 0 end) as orders_dec
+from orders o
+where o.member_id = any(%(ids)s)
+group by o.member_id;
+"""
+
+ sql_review_time = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+, t as (
+ select
+ o.member_id,
+ extract(hour from (o.order_start_time at time zone '{TZ}'))
+ + extract(minute from (o.order_start_time at time zone '{TZ}'))/60.0
+ + extract(second from (o.order_start_time at time zone '{TZ}'))/3600.0 as arrive_h,
+ extract(hour from (o.order_end_time at time zone '{TZ}'))
+ + extract(minute from (o.order_end_time at time zone '{TZ}'))/60.0
+ + extract(second from (o.order_end_time at time zone '{TZ}'))/3600.0 as leave_h_raw
+ from orders o
+ where o.member_id = any(%(ids)s)
+),
+tt as (
+ select
+ member_id,
+ arrive_h,
+ case when leave_h_raw < arrive_h then leave_h_raw + 24 else leave_h_raw end as leave_h
+ from t
+)
+select
+ member_id,
+ avg(arrive_h) as arrive_avg_h,
+ percentile_cont(0.5) within group (order by arrive_h) as arrive_med_h,
+ avg(leave_h) as leave_avg_h,
+ percentile_cont(0.5) within group (order by leave_h) as leave_med_h
+from tt
+group by member_id;
+"""
+
+ sql_review_pref = """
+select
+ tfl.member_id,
+ coalesce(tfl.site_table_area_name,'') as site_table_area_name,
+ sum(tfl.real_table_use_seconds)/3600.0 as hours
+from billiards_dwd.dwd_table_fee_log tfl
+where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz and tfl.start_use_time < %(window_end)s::timestamptz
+ and tfl.member_id = any(%(ids)s)
+group by tfl.member_id, site_table_area_name;
+"""
+
+ sql_review_goods = """
+with base_orders as (
+ select order_settle_id, max(member_id) as member_id
+ from billiards_dwd.dwd_table_fee_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz and start_use_time < %(window_end)s::timestamptz
+ group by order_settle_id
+)
+select
+ bo.member_id,
+ g.ledger_name,
+ sum(g.ledger_count) as qty,
+ sum(g.ledger_amount) as amount
+from base_orders bo
+join billiards_dwd.dwd_store_goods_sale g on g.order_settle_id = bo.order_settle_id
+where g.site_id=%(site_id)s and coalesce(g.is_delete,0)=0
+ and bo.member_id = any(%(ids)s)
+group by bo.member_id, g.ledger_name;
+"""
+
+ sql_review_visits = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+select
+ o.member_id,
+ (o.order_start_time at time zone '{TZ}')::date as visit_date,
+ count(*) as orders,
+ sum(o.order_amount) as amount
+from orders o
+where o.member_id = any(%(ids)s)
+group by o.member_id, visit_date
+order by o.member_id, visit_date;
+"""
+
+ sql_fav_dec = sql_fav_all.replace("%(window_start)s", "'2025-12-01 00:00:00+08'").replace(
+ "%(window_end)s", "'2026-01-01 00:00:00+08'"
+ )
+
+ top100 = fetch_all(cur, sql_top100, {"site_id": SITE_ID})
+ top_ids = [r["member_id"] for r in top100]
+
+ cur.execute(
+ """
+select member_id, nickname, mobile, member_card_grade_name
+from billiards_dwd.dim_member
+where scd2_is_current=1 and member_id = any(%(ids)s)
+""",
+ {"ids": top_ids},
+ )
+ info_map = {r["member_id"]: {"name": (r.get("nickname") or ""), "mobile": (r.get("mobile") or ""), "vip": (r.get("member_card_grade_name") or "")} for r in cur.fetchall()}
+
+ balances = fetch_all(cur, sql_stored_value, {"ids": top_ids})
+ balance_map = {r["member_id"]: d(r["stored_value_balance"]) for r in balances}
+
+ monthly_consume = fetch_all(cur, sql_monthly_consume, {"site_id": SITE_ID})
+ monthly_recharge = fetch_all(cur, sql_monthly_recharge, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]})
+ fav_all = fetch_all(cur, sql_fav_all, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1]})
+ fav_dec = fetch_all(cur, sql_fav_dec, {"site_id": SITE_ID})
+
+ consume_map: dict[int, dict[str, Decimal]] = {}
+ for r in monthly_consume:
+ consume_map.setdefault(r["member_id"], {})[r["month_key"]] = d(r["consume_sum"])
+
+ recharge_map: dict[int, dict[str, Decimal]] = {}
+ for r in monthly_recharge:
+ recharge_map.setdefault(r["member_id"], {})[r["month_key"]] = d(r["recharge_sum"])
+
+ fav_all_map = {r["member_id"]: (r["fav5"] or "") for r in fav_all}
+ fav_dec_map = {r["member_id"]: (r["fav5"] or "") for r in fav_dec}
+
+ rows_total: list[list[Any]] = []
+ rows_split: list[list[Any]] = []
+
+ for idx, r in enumerate(top100, start=1):
+ mid = r["member_id"]
+ info = info_map.get(mid, {"name": "", "mobile": "", "vip": ""})
+ total_rech = sum(recharge_map.get(mid, {}).values()) if recharge_map.get(mid) else Decimal("0")
+ rows_total.append([
+ idx,
+ info["name"],
+ mask_phone(info["mobile"]),
+ fav_all_map.get(mid, ""),
+ fmt_money(r["consume_total"]),
+ fmt_money(total_rech),
+ fmt_money(balance_map.get(mid, Decimal("0"))),
+ "", # 评价后续回填
+ ])
+
+ c = consume_map.get(mid, {})
+ rc = recharge_map.get(mid, {})
+ rows_split.append([
+ idx,
+ info["name"],
+ mask_phone(info["mobile"]),
+ fav_dec_map.get(mid, ""),
+ fmt_money(c.get("2025-12", Decimal("0"))),
+ fmt_money(rc.get("2025-12", Decimal("0"))),
+ fmt_money(c.get("2025-11", Decimal("0"))),
+ fmt_money(rc.get("2025-11", Decimal("0"))),
+ fmt_money(c.get("2025-10", Decimal("0"))),
+ fmt_money(rc.get("2025-10", Decimal("0"))),
+ ])
+
+ csv_total = OUT_DIR / "客户_Top100_2025年10-12月_总表.csv"
+ md_total = OUT_DIR / "客户_Top100_2025年10-12月_总表.md"
+ write_csv(
+ csv_total,
+ title_total,
+ desc_total,
+ [
+ ["排名", "客户名称", "电话号码", "10月-12月", "10月-12月", "10月-12月", "当前", "评价"],
+ ["排名", "客户名称", "电话号码", "喜爱助教昵称", "总消费(元)", "总充值(元)", "储值卡未使用金额(元)", "评价"],
+ ],
+ rows_total,
+ )
+ write_md(
+ md_total,
+ title_total,
+ thinking,
+ desc_total,
+ [
+ SqlBlock("Top100(按消费总额)", sql_top100),
+ SqlBlock("按月消费汇总", sql_monthly_consume),
+ SqlBlock("按月充值汇总", sql_monthly_recharge),
+ SqlBlock("储值卡未使用金额(当前余额汇总)", sql_stored_value),
+ SqlBlock("喜爱助教Top5(10-12月)", sql_fav_all),
+ SqlBlock("评价画像:订单/时长/到店日期", sql_review_profile),
+ SqlBlock("评价画像:到店/离店时间(小时)", sql_review_time),
+ SqlBlock("评价画像:球台分区偏好(按时长)", sql_review_pref),
+ SqlBlock("评价画像:商品明细(名称+数量)", sql_review_goods),
+ SqlBlock("评价画像:到店日期明细(用于周期/近期分析)", sql_review_visits),
+ ],
+ )
+
+ csv_split = OUT_DIR / "客户_Top100_2025年10-12月_分表.csv"
+ md_split = OUT_DIR / "客户_Top100_2025年10-12月_分表.md"
+ write_csv(
+ csv_split,
+ title_split,
+ desc_split,
+ [
+ ["排名", "客户名称", "电话号码", "12月", "12月", "12月", "11月", "11月", "10月", "10月"],
+ ["排名", "客户名称", "电话号码", "喜爱助教昵称", "消费(元)", "充值(元)", "消费(元)", "充值(元)", "消费(元)", "充值(元)"],
+ ],
+ rows_split,
+ )
+ write_md(
+ md_split,
+ title_split,
+ thinking,
+ desc_split,
+ [
+ SqlBlock("Top100(按消费总额)", sql_top100),
+ SqlBlock("按月消费汇总", sql_monthly_consume),
+ SqlBlock("按月充值汇总", sql_monthly_recharge),
+ SqlBlock("喜爱助教Top5(仅12月)", sql_fav_dec),
+ ],
+ )
+
+ return top_ids
+
+
+def backfill_customer_reviews(cur, top_ids: list[int]) -> None:
+ def csv_safe_text(text: str) -> str:
+ return (text or "").replace(",", ",").replace("\r", " ").replace("\n", " ").strip()
+
+ def fmt_clock_time(v: Any, *, prefix_next_day: bool) -> str:
+ if v is None:
+ return ""
+ minutes = int((d(v) * 60).to_integral_value(rounding="ROUND_HALF_UP"))
+ is_next_day = minutes >= 24 * 60
+ minutes = minutes % (24 * 60)
+ hh = minutes // 60
+ mm = minutes % 60
+ base = f"{hh:02d}:{mm:02d}"
+ if is_next_day and prefix_next_day:
+ return f"次日{base}"
+ return base
+
+ def norm_area(name: str | None) -> str:
+ s = (name or "").strip()
+ if not s:
+ return "未知"
+ m = re.search(r"([A-Z])区", s)
+ if m:
+ return f"{m.group(1)}区"
+ if "斯诺克" in s:
+ return "S区/斯诺克"
+ if "麻将" in s:
+ return "麻将"
+ if "K包" in s or "VIP" in s or "包厢" in s:
+ return "包厢"
+ if "团建" in s:
+ return "团建"
+ return s
+
+ # 画像(订单维度:订单、时长、到离店时间、到店日期分布)
+ sql_profile = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+, order_ext as (
+ select
+ o.*,
+ extract(epoch from (o.order_end_time - o.order_start_time)) as stay_seconds
+ from orders o
+)
+select
+ o.member_id,
+ count(*) as orders,
+ avg(o.order_amount) as avg_order,
+ sum(o.table_use_seconds)/3600.0 as play_hours,
+ avg(o.table_use_seconds)/3600.0 as avg_play_hours,
+ sum(case when o.order_start_time >= '{WIN_DEC[0]}'::timestamptz and o.order_start_time < '{WIN_DEC[1]}'::timestamptz then coalesce(o.table_use_seconds,0) else 0 end)/3600.0 as play_hours_dec,
+ min((o.order_start_time at time zone '{TZ}')::date) as first_visit_day,
+ max((o.order_start_time at time zone '{TZ}')::date) as last_visit_day,
+ count(distinct (o.order_start_time at time zone '{TZ}')::date) as visit_days,
+ count(distinct case when o.order_start_time >= '{WIN_DEC[0]}'::timestamptz and o.order_start_time < '{WIN_DEC[1]}'::timestamptz then (o.order_start_time at time zone '{TZ}')::date else null end) as visit_days_dec,
+ sum(case when o.order_start_time >= '{WIN_OCT[0]}'::timestamptz and o.order_start_time < '{WIN_OCT[1]}'::timestamptz then 1 else 0 end) as orders_oct,
+ sum(case when o.order_start_time >= '{WIN_NOV[0]}'::timestamptz and o.order_start_time < '{WIN_NOV[1]}'::timestamptz then 1 else 0 end) as orders_nov,
+ sum(case when o.order_start_time >= '{WIN_DEC[0]}'::timestamptz and o.order_start_time < '{WIN_DEC[1]}'::timestamptz then 1 else 0 end) as orders_dec,
+ sum(coalesce(o.stay_seconds,0))/3600.0 as stay_hours_total,
+ sum(case when o.order_start_time >= '{WIN_DEC[0]}'::timestamptz and o.order_start_time < '{WIN_DEC[1]}'::timestamptz then coalesce(o.stay_seconds,0) else 0 end)/3600.0 as stay_hours_dec
+from order_ext o
+where o.member_id = any(%(ids)s)
+group by o.member_id;
+"""
+
+ sql_time = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+, t as (
+ select
+ o.member_id,
+ extract(hour from (o.order_start_time at time zone '{TZ}'))
+ + extract(minute from (o.order_start_time at time zone '{TZ}'))/60.0
+ + extract(second from (o.order_start_time at time zone '{TZ}'))/3600.0 as arrive_h,
+ extract(hour from (o.order_end_time at time zone '{TZ}'))
+ + extract(minute from (o.order_end_time at time zone '{TZ}'))/60.0
+ + extract(second from (o.order_end_time at time zone '{TZ}'))/3600.0 as leave_h_raw
+ from orders o
+ where o.member_id = any(%(ids)s)
+),
+tt as (
+ select
+ member_id,
+ arrive_h,
+ case when leave_h_raw < arrive_h then leave_h_raw + 24 else leave_h_raw end as leave_h
+ from t
+)
+select
+ member_id,
+ avg(arrive_h) as arrive_avg_h,
+ percentile_cont(0.5) within group (order by arrive_h) as arrive_med_h,
+ avg(leave_h) as leave_avg_h,
+ percentile_cont(0.5) within group (order by leave_h) as leave_med_h
+from tt
+group by member_id;
+"""
+
+ prof = fetch_all(cur, sql_profile, {"site_id": SITE_ID, "ids": top_ids})
+ prof_map = {r["member_id"]: r for r in prof}
+
+ times = fetch_all(cur, sql_time, {"site_id": SITE_ID, "ids": top_ids})
+ time_map = {r["member_id"]: r for r in times}
+
+ # 偏好(按球台分区小时)
+ sql_pref = f"""
+select
+ tfl.member_id,
+ coalesce(tfl.site_table_area_name,'') as site_table_area_name,
+ sum(tfl.real_table_use_seconds)/3600.0 as hours
+from billiards_dwd.dwd_table_fee_log tfl
+where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz and tfl.start_use_time < %(window_end)s::timestamptz
+ and tfl.member_id = any(%(ids)s)
+group by tfl.member_id, site_table_area_name;
+"""
+
+ prefs = fetch_all(
+ cur,
+ sql_pref,
+ {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1], "ids": top_ids},
+ )
+ pref_map: dict[int, list[dict[str, Any]]] = {}
+ for r in prefs:
+ pref_map.setdefault(r["member_id"], []).append(r)
+
+ # 商品(名称+数量)
+ sql_food = """
+with base_orders as (
+ select order_settle_id, max(member_id) as member_id
+ from billiards_dwd.dwd_table_fee_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz and start_use_time < %(window_end)s::timestamptz
+ group by order_settle_id
+)
+select
+ bo.member_id,
+ g.ledger_name,
+ sum(g.ledger_count) as qty,
+ sum(g.ledger_amount) as amount
+from base_orders bo
+join billiards_dwd.dwd_store_goods_sale g on g.order_settle_id = bo.order_settle_id
+where g.site_id=%(site_id)s and coalesce(g.is_delete,0)=0
+ and bo.member_id = any(%(ids)s)
+group by bo.member_id, g.ledger_name;
+"""
+
+ foods = fetch_all(
+ cur,
+ sql_food,
+ {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1], "ids": top_ids},
+ )
+ food_map: dict[int, list[dict[str, Any]]] = {}
+ for r in foods:
+ food_map.setdefault(r["member_id"], []).append(r)
+
+ sql_visits = sql_order_base(WIN_ALL[0], WIN_ALL[1]) + f"""
+select
+ o.member_id,
+ (o.order_start_time at time zone '{TZ}')::date as visit_date,
+ count(*) as orders,
+ sum(o.order_amount) as amount
+from orders o
+where o.member_id = any(%(ids)s)
+group by o.member_id, visit_date
+order by o.member_id, visit_date;
+"""
+ visits = fetch_all(cur, sql_visits, {"site_id": SITE_ID, "ids": top_ids})
+ visit_map: dict[int, list[dict[str, Any]]] = {}
+ for r in visits:
+ visit_map.setdefault(r["member_id"], []).append(r)
+
+ # 喜爱助教(10-12月)
+ sql_fav = f"""
+with x as (
+ select
+ asl.tenant_member_id as member_id,
+ asl.nickname as assistant_nickname,
+ sum(case when asl.order_assistant_type=1 then asl.income_seconds else asl.income_seconds*1.5 end) / 3600.0 as weighted_hours
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.tenant_member_id = any(%(ids)s)
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ group by asl.tenant_member_id, asl.nickname
+),
+ranked as (
+ select *, row_number() over(partition by member_id order by weighted_hours desc) as rn
+ from x
+)
+select
+ member_id,
+ string_agg(assistant_nickname || '(' || to_char(round(weighted_hours::numeric, 1), 'FM999999990.0') || 'h)', '、' order by weighted_hours desc) as fav5
+from ranked
+where rn <= 5
+group by member_id;
+"""
+
+ favs = fetch_all(cur, sql_fav, {"site_id": SITE_ID, "window_start": WIN_ALL[0], "window_end": WIN_ALL[1], "ids": top_ids})
+ fav_map = {r["member_id"]: (r["fav5"] or "") for r in favs}
+
+ # 到店周期中位(天)与排名:以 Top100 为比较集合;值越小表示到店越频繁,排名越靠前
+ gap_med_all: dict[int, int] = {}
+ gap_med_dec: dict[int, int] = {}
+ for mid in top_ids:
+ vrows = visit_map.get(mid, [])
+ dates_all = [r.get("visit_date") for r in vrows if r.get("visit_date")]
+ gaps_all: list[int] = []
+ for d1, d2 in zip(dates_all, dates_all[1:]):
+ gaps_all.append((d2 - d1).days)
+ if gaps_all:
+ gaps_sorted = sorted(gaps_all)
+ gap_med_all[mid] = gaps_sorted[len(gaps_sorted) // 2]
+
+ dates_dec = [d for d in dates_all if d.year == 2025 and d.month == 12]
+ gaps_dec: list[int] = []
+ for d1, d2 in zip(dates_dec, dates_dec[1:]):
+ gaps_dec.append((d2 - d1).days)
+ if gaps_dec:
+ gaps_sorted = sorted(gaps_dec)
+ gap_med_dec[mid] = gaps_sorted[len(gaps_sorted) // 2]
+
+ def dense_rank(values: list[tuple[int, Any]], *, reverse: bool) -> dict[int, int]:
+ sorted_vals = sorted(values, key=lambda kv: kv[1], reverse=reverse)
+ out: dict[int, int] = {}
+ last_v = None
+ rank = 0
+ for mid, v in sorted_vals:
+ if last_v is None or v != last_v:
+ rank += 1
+ last_v = v
+ out[mid] = rank
+ return out
+
+ gap_rank_all = dense_rank([(mid, v) for mid, v in gap_med_all.items()], reverse=False)
+ gap_rank_dec = dense_rank([(mid, v) for mid, v in gap_med_dec.items()], reverse=False)
+
+ # 在店时长:用台费使用时长(real_table_use_seconds 汇总到 orders.table_use_seconds)作为“在店时长”近似
+ play_rank_all = dense_rank(
+ [(mid, d(prof_map.get(mid, {}).get("play_hours"))) for mid in top_ids if d(prof_map.get(mid, {}).get("play_hours")) > 0],
+ reverse=True,
+ )
+ play_rank_dec = dense_rank(
+ [(mid, d(prof_map.get(mid, {}).get("play_hours_dec"))) for mid in top_ids if d(prof_map.get(mid, {}).get("play_hours_dec")) > 0],
+ reverse=True,
+ )
+
+ def build_review(
+ mid: int,
+ rank: int,
+ consume_total: Decimal,
+ recharge_total: Decimal,
+ stored_value_balance: Decimal,
+ ) -> str:
+ p = prof_map.get(mid) or {}
+ orders = int(p.get("orders") or 0)
+ if orders <= 0:
+ return ""
+ avg_order = d(p.get("avg_order"))
+ play_h = d(p.get("play_hours"))
+ avg_play_h = d(p.get("avg_play_hours"))
+
+ # 偏好:球台分区Top(按时长)
+ areas_raw = pref_map.get(mid, [])
+ area_hours: dict[str, Decimal] = {}
+ for r in areas_raw:
+ label = norm_area(r.get("site_table_area_name"))
+ area_hours[label] = area_hours.get(label, Decimal("0")) + d(r.get("hours"))
+ area_items = sorted(area_hours.items(), key=lambda kv: kv[1], reverse=True)
+ area_total = sum((v for _, v in area_items), Decimal("0"))
+ pref_text = ""
+ if area_total > 0 and area_items:
+ top_parts = []
+ for label, hours in area_items[:4]:
+ pct = (hours / area_total * 100).quantize(Decimal("1.0"))
+ top_parts.append(f"{label}({pct}%)")
+ pref_text = "、".join(top_parts)
+
+ # 时间:到店/离店(小时)
+ t = time_map.get(mid) or {}
+ time_text = ""
+ if t:
+ a_avg = fmt_clock_time(t.get("arrive_avg_h"), prefix_next_day=False)
+ a_med = fmt_clock_time(t.get("arrive_med_h"), prefix_next_day=False)
+ l_avg = fmt_clock_time(t.get("leave_avg_h"), prefix_next_day=True)
+ l_med = fmt_clock_time(t.get("leave_med_h"), prefix_next_day=True)
+ if a_avg and a_med and l_avg and l_med:
+ time_text = f"到店均值{a_avg} 中位{a_med};离店均值{l_avg} 中位{l_med}"
+
+ # 商品:名称+数量+金额
+ foods_ = food_map.get(mid, [])
+ foods_.sort(key=lambda r: d(r["amount"]), reverse=True)
+ goods_total = sum((d(r["amount"]) for r in foods_), Decimal("0"))
+ goods_text = ""
+ if foods_:
+ parts = []
+ for r in foods_[:6]:
+ name = csv_safe_text(str(r.get("ledger_name") or ""))
+ qty = d(r.get("qty"))
+ amt = d(r.get("amount"))
+ if not name:
+ continue
+ qty_i = int(qty) if qty == qty.to_integral_value() else qty
+ parts.append(f"{name}×{qty_i}(¥{amt:.2f})")
+ if parts:
+ goods_text = "、".join(parts)
+ if consume_total > 0 and goods_total > 0:
+ ratio = (goods_total / consume_total * 100).quantize(Decimal("1.0"))
+ goods_text = f"{goods_text}(商品合计¥{goods_total:.2f} 占比{ratio}%)"
+
+ # 到店周期/近期分布(按到店日期)
+ vrows = visit_map.get(mid, [])
+ visit_dates = [r.get("visit_date") for r in vrows if r.get("visit_date")]
+ last_day = p.get("last_visit_day")
+ visit_days = int(p.get("visit_days") or 0)
+ visit_days_dec = int(p.get("visit_days_dec") or 0)
+ orders_dec = int(p.get("orders_dec") or 0)
+
+ # 趋势:按月订单数粗略判断(仅Top100客户画像用途)
+ orders_oct = int(p.get("orders_oct") or 0)
+ orders_nov = int(p.get("orders_nov") or 0)
+ orders_dec2 = int(p.get("orders_dec") or 0)
+ if orders_dec2 > orders_nov >= orders_oct:
+ trend = "10-12月到店频次上升,12月更活跃"
+ elif orders_oct > orders_nov > orders_dec2:
+ trend = "10-12月到店频次下降,建议重点唤醒"
+ elif orders_dec2 >= orders_oct and orders_dec2 >= orders_nov:
+ trend = "12月为高峰月,具备加深运营空间"
+ else:
+ trend = "到店频次波动,建议按常用时段做稳定触达"
+
+ # 运营建议(尽量简短、可执行)
+ advice_parts: list[str] = []
+ if stored_value_balance <= 0 and recharge_total > 0:
+ advice_parts.append("关注是否为临时充值型,建议引导储值梯度与权益")
+ if stored_value_balance > 0 and stored_value_balance < Decimal("500"):
+ advice_parts.append("储值余额偏低,建议在其常用时段做补能引导")
+ if stored_value_balance >= Decimal("10000"):
+ advice_parts.append("储值余额充足,可提供包厢/团建档期与专属权益")
+ if pref_text and ("包厢" in pref_text or "团建" in pref_text):
+ advice_parts.append("重点维护包厢/团建需求,提前锁档与套餐化")
+ if goods_total >= Decimal("2000"):
+ advice_parts.append("商品贡献高,可做常购商品补货提醒与组合促销")
+ if not advice_parts:
+ advice_parts.append("保持常用时段的稳定服务供给,提升复购粘性")
+ advice = ";".join(advice_parts[:3])
+
+ # 综合(按你给的格式组织;排名基于Top100集合)
+ gap_rank_all_text = f"#{gap_rank_all.get(mid)}" if gap_rank_all.get(mid) else "—"
+ gap_rank_dec_text = f"#{gap_rank_dec.get(mid)}" if gap_rank_dec.get(mid) else "—"
+ play_rank_all_text = f"#{play_rank_all.get(mid)}" if play_rank_all.get(mid) else "—"
+ play_rank_dec_text = f"#{play_rank_dec.get(mid)}" if play_rank_dec.get(mid) else "—"
+
+ composite_lines = []
+ composite_lines.append(
+ f"10-12月到店消费{visit_days}天/{orders}次,到店周期中位{gap_rank_all_text},消费排名#{rank},在店时长{play_rank_all_text}"
+ )
+ composite_lines.append(
+ f"12月到店消费{visit_days_dec}天/{orders_dec}次,到店周期中位{gap_rank_dec_text},消费排名#{rank},在店时长{play_rank_dec_text}"
+ )
+ if last_day:
+ composite_lines.append(f"最近到店{last_day}")
+ composite_lines.append(f"趋势:{trend}")
+ composite_lines.append(f"围客与客户运营建议:{advice}")
+
+ parts = [
+ f"订单:{orders}单,平均单次¥{avg_order:.2f}",
+ f"打球:{fmt_hours(play_h,1)},平均单次{fmt_hours(avg_play_h,1)}",
+ ]
+ if pref_text:
+ parts.append(f"偏好:{pref_text}")
+ if time_text:
+ parts.append(f"时间:{time_text}")
+ if goods_text:
+ parts.append(f"商品:{goods_text}")
+ parts.append("综合:" + ";".join([x for x in composite_lines if x]))
+
+ return csv_safe_text(";".join([p for p in parts if p]))
+
+ # 回写 CSV(保留原有总消费/总充值/储值余额/助教偏好,只更新评价列)
+ csv_total = OUT_DIR / "客户_Top100_2025年10-12月_总表.csv"
+ if not csv_total.exists():
+ return
+
+ lines = csv_total.read_text(encoding="utf-8").splitlines()
+ # CSV:前3行是标题、说明、空行;接着2行表头;后面是数据
+ head = lines[:5]
+ data_lines = lines[5:]
+
+ # 解析数据行(简单 split,避免引号复杂情况:本脚本生成的行不含逗号)
+ new_data = []
+ for idx, line in enumerate(data_lines, start=1):
+ cols = line.split(",")
+ if len(cols) < 8:
+ new_data.append(line)
+ continue
+ # 按排名映射 member_id
+ rank = int(cols[0])
+ mid = top_ids[rank - 1] if 0 < rank <= len(top_ids) else None
+ if mid:
+ consume_total = d(cols[4])
+ recharge_total = d(cols[5])
+ stored_value_balance = d(cols[6])
+ cols[7] = build_review(mid, rank, consume_total, recharge_total, stored_value_balance)
+ new_data.append(",".join(cols))
+
+ csv_total.write_text("\n".join(head + new_data) + "\n", encoding="utf-8")
+
+
+def main() -> None:
+ OUT_DIR.mkdir(parents=True, exist_ok=True)
+ with conn() as c, c.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur:
+ build_finance_discount(cur)
+ top_ids = build_customer_top100(cur)
+ backfill_customer_reviews(cur, top_ids)
+
+ print(f"完成:{OUT_DIR}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.csv b/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.csv
new file mode 100644
index 0000000..3032bdc
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.csv
@@ -0,0 +1,73 @@
+2025年10-12月 助教基础课时长排行榜
+口径:order_assistant_type=1,时长=income_seconds/3600(小时),按月排名。
+
+月份,排名,助教昵称,指标
+2025-10,1,佳怡,139.55h
+2025-10,2,璇子,120.20h
+2025-10,3,婉婉,90.68h
+2025-10,4,七七,64.70h
+2025-10,5,小柔,63.87h
+2025-10,6,球球,57.45h
+2025-10,7,小敌,55.82h
+2025-10,8,涛涛,50.13h
+2025-10,9,周周,41.33h
+2025-10,10,素素,40.45h
+2025-10,11,乔西,32.60h
+2025-10,12,苏苏,25.15h
+2025-10,13,奈千,23.62h
+2025-10,14,年糕,21.23h
+2025-10,15,欣怡,19.50h
+2025-10,16,饭团,16.00h
+2025-10,17,Amy,11.97h
+2025-10,18,姜姜,6.60h
+2025-10,19,希希,5.02h
+2025-10,20,悦悦,2.30h
+2025-11,1,佳怡,176.25h
+2025-11,2,璇子,147.92h
+2025-11,3,小燕,109.28h
+2025-11,4,Amy,93.53h
+2025-11,5,七七,91.90h
+2025-11,6,小柔,88.65h
+2025-11,7,涛涛,74.40h
+2025-11,8,阿清,73.48h
+2025-11,9,小敌,72.90h
+2025-11,10,周周,71.27h
+2025-11,11,球球,66.50h
+2025-11,12,婉婉,46.03h
+2025-11,13,小侯,42.58h
+2025-11,14,千千,38.88h
+2025-11,15,年糕,35.80h
+2025-11,16,柚子,35.40h
+2025-11,17,素素,35.03h
+2025-11,18,瑶瑶,34.25h
+2025-11,19,奈千,32.83h
+2025-11,20,乔西,30.57h
+2025-11,21,泡芙,21.38h
+2025-11,22,梦梦,19.60h
+2025-11,23,苏苏,13.52h
+2025-11,24,欣怡,10.33h
+2025-11,25,QQ,5.17h
+2025-11,26,西子,1.82h
+2025-11,27,希希,1.58h
+2025-12,1,小燕,159.02h
+2025-12,2,佳怡,109.40h
+2025-12,3,璇子,90.75h
+2025-12,4,七七,77.72h
+2025-12,5,阿清,66.45h
+2025-12,6,周周,60.02h
+2025-12,7,小柔,54.93h
+2025-12,8,小侯,49.57h
+2025-12,9,球球,48.58h
+2025-12,10,涛涛,44.08h
+2025-12,11,苏苏,43.90h
+2025-12,12,千千,38.28h
+2025-12,13,乔西,25.82h
+2025-12,14,年糕,25.62h
+2025-12,15,瑶瑶,19.48h
+2025-12,16,Amy,18.08h
+2025-12,17,婉婉,17.83h
+2025-12,18,梦梦,16.08h
+2025-12,19,素素,9.98h
+2025-12,20,小敌,6.40h
+2025-12,21,奈千,2.58h
+2025-12,22,QQ,1.22h
diff --git a/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.md b/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.md
new file mode 100644
index 0000000..0cfa257
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_基础课时长排行_2025年10-12月.md
@@ -0,0 +1,31 @@
+# 2025年10-12月 助教基础课时长排行榜
+## 思考过程
+按月汇总助教基础课时长,并用 dense_rank 做排名。
+
+## 查询说明
+口径:order_assistant_type=1;时长=income_seconds/3600(小时)。
+
+## SQL
+
+### 基础课时长(助教+月份汇总)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.order_assistant_type=1
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+)
+select
+ assistant,
+ month_key,
+ sum(income_seconds)/3600.0 as hours
+from raw
+where month_key is not null
+group by assistant, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.csv b/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.csv
new file mode 100644
index 0000000..cc075d5
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.csv
@@ -0,0 +1,35 @@
+2025年10-12月 助教客户充值归因排行榜(全额复制口径)
+口径:充值支付(dwd_payment.relate_type=5)在消费窗口±30分钟内命中且订单有助教,则全额计入助教;多助教/多订单命中会重复计入。
+
+月份,排名,助教昵称,指标
+2025-10,1,璇子,34700.00
+2025-10,2,小柔,31700.00
+2025-10,3,佳怡,27000.00
+2025-10,4,婉婉,24000.00
+2025-10,5,小敌,21000.00
+2025-10,5,涛涛,21000.00
+2025-10,6,奈千,18000.00
+2025-10,7,乔西,17000.00
+2025-10,8,球球,15000.00
+2025-10,9,周周,11000.00
+2025-10,10,年糕,9000.00
+2025-10,11,七七,6000.00
+2025-10,11,素素,6000.00
+2025-10,11,苏苏,6000.00
+2025-10,12,姜姜,4000.00
+2025-10,13,Amy,3000.00
+2025-10,13,悦悦,3000.00
+2025-10,13,欣怡,3000.00
+2025-11,1,佳怡,20000.00
+2025-11,2,小柔,11000.00
+2025-11,3,璇子,10000.00
+2025-11,4,Amy,9000.00
+2025-11,4,周周,9000.00
+2025-11,4,婉婉,9000.00
+2025-11,4,球球,9000.00
+2025-11,5,小敌,8000.00
+2025-11,6,涛涛,5000.00
+2025-11,7,欣怡,4000.00
+2025-11,8,乔西,3000.00
+2025-11,8,柚子,3000.00
+2025-11,9,素素,1000.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.md b/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.md
new file mode 100644
index 0000000..1050c8c
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_客户充值归因排行_2025年10-12月.md
@@ -0,0 +1,85 @@
+# 2025年10-12月 助教客户充值归因排行榜(全额复制口径)
+## 思考过程
+按“消费窗口±30分钟”把充值支付命中到订单,再全额计入订单内助教,并按月排名。
+
+## 查询说明
+注意:多助教/多订单命中按全额复制,充值会重复计入,故助教汇总可能大于门店总额。
+
+## SQL
+
+### 充值归因(助教+月份汇总,全额复制)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select rp.pay_time, ow.order_settle_id, rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select assistant, month_key, sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.csv b/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.csv
new file mode 100644
index 0000000..204968c
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.csv
@@ -0,0 +1,51 @@
+2025年10-12月 助教客户流水排行榜(全额复制口径)
+口径:客户流水=台费+助教+商品应付金额按订单归集后,全额计入订单内每位助教;多助教会导致汇总>门店总额。
+
+月份,排名,助教昵称,指标
+2025-10,1,璇子,80804.14
+2025-10,2,婉婉,62187.64
+2025-10,3,小柔,52623.85
+2025-10,4,小敌,44510.29
+2025-10,5,佳怡,44466.03
+2025-10,6,七七,38810.44
+2025-10,7,奈千,38653.58
+2025-10,8,涛涛,35940.84
+2025-10,9,素素,34135.89
+2025-10,10,球球,33923.75
+2025-10,11,周周,27375.91
+2025-10,12,年糕,26289.89
+2025-10,13,乔西,17649.50
+2025-10,14,Amy,15810.80
+2025-10,15,苏苏,11236.84
+2025-10,16,饭团,7955.28
+2025-10,17,欣怡,4824.69
+2025-10,18,希希,3086.34
+2025-10,19,悦悦,2970.96
+2025-10,20,姜姜,2333.94
+2025-11,1,璇子,154486.83
+2025-11,2,Amy,121568.32
+2025-11,3,小柔,110137.94
+2025-11,4,涛涛,88677.55
+2025-11,5,七七,84500.79
+2025-11,6,佳怡,79249.31
+2025-11,7,奈千,68543.08
+2025-11,8,瑶瑶,65924.36
+2025-11,9,小敌,47986.57
+2025-11,10,球球,41907.39
+2025-11,11,梦梦,39768.09
+2025-11,12,小燕,39426.42
+2025-11,13,阿清,37302.04
+2025-11,14,婉婉,33326.32
+2025-11,15,周周,31436.74
+2025-11,16,小侯,27313.21
+2025-11,17,千千,24684.71
+2025-11,18,柚子,23234.98
+2025-11,19,素素,18707.30
+2025-11,20,年糕,15696.08
+2025-11,21,乔西,15536.78
+2025-11,22,苏苏,10254.59
+2025-11,23,泡芙,8323.03
+2025-11,24,欣怡,5157.29
+2025-11,25,QQ,1134.18
+2025-11,26,西子,303.51
+2025-11,27,希希,281.22
diff --git a/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.md b/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.md
new file mode 100644
index 0000000..8d68e7c
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_客户流水排行_2025年10-12月.md
@@ -0,0 +1,73 @@
+# 2025年10-12月 助教客户流水排行榜(全额复制口径)
+## 思考过程
+先把订单应付金额汇总为 order_amount,再把该订单全额计入订单内每位助教,并按月排名。
+
+## 查询说明
+注意:多助教按全额复制计入,导致助教汇总>门店总额,这是刻意口径。
+
+## SQL
+
+### 客户流水(助教+月份汇总,全额复制)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id=g.order_settle_id
+ where g.site_id=%(site_id)s and coalesce(g.is_delete,0)=0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ coalesce(bo.table_amount,0)+coalesce(a.assistant_amount,0)+coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id=bo.order_settle_id
+ left join goods_amount g on g.order_settle_id=bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+)
+select assistant, month_key, sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.csv b/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.csv
new file mode 100644
index 0000000..902ea41
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.csv
@@ -0,0 +1,37 @@
+2025年10-12月 助教附加课(超休)时长排行榜
+口径:order_assistant_type=2,超休时长=income_seconds/3600(小时),按月排名。
+
+月份,排名,助教昵称,指标
+2025-10,1,球球,11.00h
+2025-10,2,佳怡,9.00h
+2025-10,3,璇子,8.00h
+2025-10,3,苏苏,8.00h
+2025-10,4,婉婉,4.00h
+2025-10,5,姜姜,3.00h
+2025-10,5,小敌,3.00h
+2025-11,1,周周,25.00h
+2025-11,1,球球,25.00h
+2025-11,2,婉婉,15.00h
+2025-11,3,佳怡,10.00h
+2025-11,3,柚子,10.00h
+2025-11,3,璇子,10.00h
+2025-11,3,素素,10.00h
+2025-11,4,小柔,7.00h
+2025-11,4,年糕,7.00h
+2025-11,5,泡芙,3.00h
+2025-11,5,涛涛,3.00h
+2025-11,5,瑶瑶,3.00h
+2025-11,6,小燕,2.00h
+2025-11,7,乔西,1.00h
+2025-11,7,梦梦,1.00h
+2025-12,1,七七,22.00h
+2025-12,2,小燕,21.00h
+2025-12,3,婉婉,15.00h
+2025-12,3,小柔,15.00h
+2025-12,4,璇子,14.00h
+2025-12,5,周周,8.00h
+2025-12,6,千千,5.00h
+2025-12,6,球球,5.00h
+2025-12,7,佳怡,4.00h
+2025-12,8,QQ,3.00h
+2025-12,9,苏苏,1.00h
diff --git a/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.md b/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.md
new file mode 100644
index 0000000..e8986cb
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教_附加课时长排行_2025年10-12月.md
@@ -0,0 +1,31 @@
+# 2025年10-12月 助教附加课(超休)时长排行榜
+## 思考过程
+按月汇总助教附加课时长,并用 dense_rank 做排名。
+
+## 查询说明
+口径:order_assistant_type=2;时长=income_seconds/3600(小时)。
+
+## SQL
+
+### 附加课时长(助教+月份汇总)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.order_assistant_type=2
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+)
+select
+ assistant,
+ month_key,
+ sum(income_seconds)/3600.0 as hours
+from raw
+where month_key is not null
+group by assistant, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_Amy.csv b/etl_billiards/docs/table_2025-12-19/助教详情_Amy.csv
new file mode 100644
index 0000000..bad2eac
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_Amy.csv
@@ -0,0 +1,56 @@
+助教详情:Amy(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础123.6h,附加0.0h;客户流水¥150692.64,充值归因¥12000.00;头部客户(12月)Top3:轩哥、明哥、江先生。
+
+一、基础课业绩
+说明:评价:基础123.6h,附加0.0h;客户流水¥150692.64,充值归因¥12000.00;头部客户(12月)Top3:轩哥、明哥、江先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,11.97h,17,-32.44h,-24.56h
+11月,93.53h,4,39.06h,54.65h
+12月,18.08h,16,-26.73h,-23.01h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,15810.80,14,-13468.73,-14839.03
+11月,121568.32,2,77313.93,88242.00
+12月,13313.52,12,-7417.01,-327.12
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,3000.00,13,-11466.67,-10000.00
+11月,9000.00,4,1230.77,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,轩哥,8.8h / 0.0h,4500.95,0.00,36.0h / 0.0h,38175.17,0.00,4.6h / 0.0h,8281.61,0.00
+2,明哥,0.1h / 0.0h,4190.45,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,江先生,2.2h / 0.0h,3202.78,0.00,4.5h / 0.0h,1719.24,0.00,0.0h / 0.0h,0.00,0.00
+4,amy,4.8h / 0.0h,1105.90,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+5,小燕,1.0h / 0.0h,313.44,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,叶先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,7.4h / 0.0h,7529.19,3000.00
+7,羊,0.0h / 0.0h,0.00,0.00,4.1h / 0.0h,1017.50,1000.00,0.0h / 0.0h,0.00,0.00
+8,葛先生,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,1585.38,0.00,0.0h / 0.0h,0.00,0.00
+9,陈先生,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,2566.75,3000.00,0.0h / 0.0h,0.00,0.00
+10,李先生,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,816.28,0.00,0.0h / 0.0h,0.00,0.00
+11,蔡总,1.2h / 0.0h,0.00,0.00,40.2h / 0.0h,75063.98,5000.00,0.0h / 0.0h,0.00,0.00
+12,昌哥,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,624.02,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_Amy.md b/etl_billiards/docs/table_2025-12-19/助教详情_Amy.md
new file mode 100644
index 0000000..dda6894
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_Amy.md
@@ -0,0 +1,196 @@
+# 助教详情:Amy(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础123.6h,附加0.0h;客户流水¥150692.64,充值归因¥12000.00;头部客户(12月)Top3:轩哥、明哥、江先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_QQ.csv b/etl_billiards/docs/table_2025-12-19/助教详情_QQ.csv
new file mode 100644
index 0000000..af1c043
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_QQ.csv
@@ -0,0 +1,47 @@
+助教详情:QQ(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础6.4h,附加3.0h;客户流水¥1517.46,充值归因¥0.00;头部客户(12月)Top3:游、张先生、黄先生。
+
+一、基础课业绩
+说明:评价:基础6.4h,附加3.0h;客户流水¥1517.46,充值归因¥0.00;头部客户(12月)Top3:游、张先生、黄先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,5.17h,25,-49.31h,-33.72h
+12月,1.22h,22,-43.59h,-39.88h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,3.00h,8,-7.27h,-5.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,1134.18,25,-43120.21,-32192.14
+12月,383.28,21,-20347.25,-13257.36
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,游,1.2h / 0.0h,383.28,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+2,张先生,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,502.16,0.00,0.0h / 0.0h,0.00,0.00
+3,黄先生,0.0h / 3.0h,0.00,0.00,2.4h / 0.0h,632.02,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_QQ.md b/etl_billiards/docs/table_2025-12-19/助教详情_QQ.md
new file mode 100644
index 0000000..040c778
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_QQ.md
@@ -0,0 +1,196 @@
+# 助教详情:QQ(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础6.4h,附加3.0h;客户流水¥1517.46,充值归因¥0.00;头部客户(12月)Top3:游、张先生、黄先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_七七.csv b/etl_billiards/docs/table_2025-12-19/助教详情_七七.csv
new file mode 100644
index 0000000..47420c2
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_七七.csv
@@ -0,0 +1,56 @@
+助教详情:七七(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础234.3h,附加22.0h;客户流水¥187346.62,充值归因¥6000.00;头部客户(12月)Top3:蔡总、轩哥、林先生。
+
+一、基础课业绩
+说明:评价:基础234.3h,附加22.0h;客户流水¥187346.62,充值归因¥6000.00;头部客户(12月)Top3:蔡总、轩哥、林先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,64.70h,4,20.29h,28.17h
+11月,91.90h,5,37.42h,53.02h
+12月,77.72h,4,32.91h,36.62h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,22.00h,1,11.73h,14.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,38810.44,6,9530.91,8160.61
+11月,84500.79,5,40246.40,51174.47
+12月,64035.39,2,43304.86,50394.74
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,6000.00,11,-8466.67,-7000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,蔡总,26.6h / 0.0h,29660.33,0.00,45.7h / 0.0h,52373.96,0.00,0.0h / 0.0h,0.00,0.00
+2,轩哥,32.8h / 22.0h,27236.57,0.00,24.2h / 0.0h,21849.91,0.00,39.5h / 0.0h,29630.52,3000.00
+3,林先生,14.0h / 0.0h,3808.56,0.00,5.4h / 0.0h,1623.92,0.00,0.0h / 0.0h,0.00,0.00
+4,江先生,3.2h / 0.0h,3042.99,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+5,张先生,1.0h / 0.0h,286.94,0.00,10.9h / 0.0h,3995.10,0.00,13.2h / 0.0h,5315.81,0.00
+6,游,0.0h / 0.0h,0.00,0.00,0.2h / 0.0h,3544.42,0.00,0.0h / 0.0h,0.00,0.00
+7,罗先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.1h / 0.0h,545.55,0.00
+8,小熊,0.0h / 0.0h,0.00,0.00,1.3h / 0.0h,314.44,0.00,0.0h / 0.0h,0.00,0.00
+9,叶总,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.0h / 0.0h,862.68,0.00
+10,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,1278.72,0.00
+11,T,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,1177.16,3000.00
+12,胡先生,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,799.04,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_七七.md b/etl_billiards/docs/table_2025-12-19/助教详情_七七.md
new file mode 100644
index 0000000..4cb7dde
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_七七.md
@@ -0,0 +1,196 @@
+# 助教详情:七七(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础234.3h,附加22.0h;客户流水¥187346.62,充值归因¥6000.00;头部客户(12月)Top3:蔡总、轩哥、林先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_乔西.csv b/etl_billiards/docs/table_2025-12-19/助教详情_乔西.csv
new file mode 100644
index 0000000..cbd3b25
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_乔西.csv
@@ -0,0 +1,59 @@
+助教详情:乔西(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础89.0h,附加1.0h;客户流水¥46219.50,充值归因¥20000.00;头部客户(12月)Top3:轩哥、T、林先生。
+
+一、基础课业绩
+说明:评价:基础89.0h,附加1.0h;客户流水¥46219.50,充值归因¥20000.00;头部客户(12月)Top3:轩哥、T、林先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,32.60h,11,-11.81h,-3.93h
+11月,30.57h,20,-23.91h,-8.32h
+12月,25.82h,13,-18.99h,-15.28h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,1.00h,7,-7.80h,-6.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,17649.50,13,-11630.03,-13000.33
+11月,15536.78,21,-28717.61,-17789.54
+12月,13033.22,13,-7697.31,-607.42
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,17000.00,7,2533.33,4000.00
+11月,3000.00,8,-4769.23,-6000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,轩哥,8.2h / 0.0h,8244.84,0.00,8.3h / 0.0h,7623.25,0.00,9.3h / 0.0h,11503.53,8000.00
+2,T,6.8h / 0.0h,1789.02,0.00,4.4h / 0.0h,1100.80,0.00,0.0h / 0.0h,0.00,0.00
+3,林先生,4.6h / 0.0h,1369.51,0.00,5.0h / 0.0h,1645.89,0.00,0.0h / 0.0h,0.00,0.00
+4,张先生,3.3h / 0.0h,1066.81,0.00,0.0h / 0.0h,0.00,0.00,2.5h / 0.0h,489.66,0.00
+5,候,2.9h / 0.0h,563.04,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,罗先生,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,454.46,0.00,0.0h / 0.0h,0.00,0.00
+7,陈腾鑫,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.9h / 0.0h,162.29,3000.00
+8,葛先生,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,707.97,0.00,0.0h / 0.0h,0.00,0.00
+9,陈先生,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,2566.75,3000.00,0.0h / 0.0h,0.00,0.00
+10,陈淑涛,0.0h / 0.0h,0.00,0.00,3.4h / 0.0h,1021.49,0.00,0.0h / 0.0h,0.00,0.00
+11,周先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,7.5h / 0.0h,2726.01,0.00
+12,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 1.0h,0.00,0.00,7.6h / 0.0h,1568.91,5000.00
+13,黄先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,300.37,0.00
+14,陈先生,0.0h / 0.0h,0.00,0.00,1.8h / 0.0h,416.17,0.00,0.0h / 0.0h,0.00,0.00
+15,方先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.2h / 0.0h,898.73,1000.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_乔西.md b/etl_billiards/docs/table_2025-12-19/助教详情_乔西.md
new file mode 100644
index 0000000..1d4e6a0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_乔西.md
@@ -0,0 +1,196 @@
+# 助教详情:乔西(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础89.0h,附加1.0h;客户流水¥46219.50,充值归因¥20000.00;头部客户(12月)Top3:轩哥、T、林先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.csv b/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.csv
new file mode 100644
index 0000000..f62f7b6
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.csv
@@ -0,0 +1,63 @@
+助教详情:佳怡(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础425.2h,附加23.0h;客户流水¥156229.68,充值归因¥47000.00;头部客户(12月)Top3:罗先生、周周、轩哥。
+
+一、基础课业绩
+说明:评价:基础425.2h,附加23.0h;客户流水¥156229.68,充值归因¥47000.00;头部客户(12月)Top3:罗先生、周周、轩哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,139.55h,1,95.14h,103.02h
+11月,176.25h,1,121.77h,137.37h
+12月,109.40h,2,64.59h,68.31h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,9.00h,2,2.43h,1.00h
+11月,10.00h,3,1.20h,3.00h
+12月,4.00h,7,-6.27h,-4.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,44466.03,5,15186.50,13816.20
+11月,79249.31,6,34994.92,45922.99
+12月,32514.34,6,11783.81,18873.70
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,27000.00,3,12533.33,14000.00
+11月,20000.00,1,12230.77,11000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,罗先生,67.8h / 4.0h,16680.01,0.00,57.5h / 10.0h,12309.26,0.00,46.9h / 8.0h,12047.56,7000.00
+2,周周,13.2h / 0.0h,3866.19,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,轩哥,6.4h / 0.0h,3741.42,0.00,18.0h / 0.0h,24036.03,0.00,24.6h / 1.0h,17999.86,3000.00
+4,大G,9.5h / 0.0h,2623.97,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+5,T,1.9h / 0.0h,2053.02,0.00,5.0h / 0.0h,2490.70,0.00,8.1h / 0.0h,1323.17,3000.00
+6,林先生,4.5h / 0.0h,1720.12,0.00,10.4h / 0.0h,3269.81,0.00,0.0h / 0.0h,0.00,0.00
+7,游,3.2h / 0.0h,1307.16,0.00,10.3h / 0.0h,4754.69,0.00,0.0h / 0.0h,0.00,0.00
+8,胡先生,3.0h / 0.0h,522.45,0.00,26.4h / 0.0h,9712.14,13000.00,0.0h / 0.0h,0.00,0.00
+9,江先生,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,1374.85,0.00,0.0h / 0.0h,0.00,0.00
+10,陈先生,0.0h / 0.0h,0.00,0.00,7.6h / 0.0h,2566.75,3000.00,0.0h / 0.0h,0.00,0.00
+11,陈腾鑫,0.0h / 0.0h,0.00,0.00,19.2h / 0.0h,4276.97,1000.00,38.5h / 0.0h,7626.75,12000.00
+12,张先生,0.0h / 0.0h,0.00,0.00,4.9h / 0.0h,2233.65,0.00,0.0h / 0.0h,0.00,0.00
+13,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,361.38,0.00
+14,夏,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,455.03,0.00,5.8h / 0.0h,2595.54,1000.00
+15,小熊,0.0h / 0.0h,0.00,0.00,6.4h / 0.0h,2072.54,3000.00,6.8h / 0.0h,1213.06,1000.00
+16,蔡总,0.0h / 0.0h,0.00,0.00,4.5h / 0.0h,9696.89,0.00,0.0h / 0.0h,0.00,0.00
+17,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.7h / 0.0h,337.17,0.00
+18,贺斌,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,247.34,0.00
+19,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.1h / 0.0h,714.20,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.md b/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.md
new file mode 100644
index 0000000..a524aa2
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_佳怡.md
@@ -0,0 +1,196 @@
+# 助教详情:佳怡(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础425.2h,附加23.0h;客户流水¥156229.68,充值归因¥47000.00;头部客户(12月)Top3:罗先生、周周、轩哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_千千.csv b/etl_billiards/docs/table_2025-12-19/助教详情_千千.csv
new file mode 100644
index 0000000..a3f43c0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_千千.csv
@@ -0,0 +1,55 @@
+助教详情:千千(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础77.2h,附加5.0h;客户流水¥34297.90,充值归因¥0.00;头部客户(12月)Top3:张先生、周先生、陈腾鑫。
+
+一、基础课业绩
+说明:评价:基础77.2h,附加5.0h;客户流水¥34297.90,充值归因¥0.00;头部客户(12月)Top3:张先生、周先生、陈腾鑫。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,38.88h,14,-15.59h,0.00h
+12月,38.28h,12,-6.53h,-2.81h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,5.00h,6,-5.27h,-3.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,24684.71,17,-19569.68,-8641.61
+12月,9613.19,16,-11117.34,-4027.46
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,张先生,10.0h / 0.0h,2622.05,0.00,4.4h / 0.0h,1623.68,0.00,0.0h / 0.0h,0.00,0.00
+2,周先生,8.6h / 0.0h,1577.94,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,陈腾鑫,4.8h / 0.0h,1375.20,0.00,2.9h / 0.0h,2418.94,0.00,0.0h / 0.0h,0.00,0.00
+4,梅,3.3h / 5.0h,1356.34,0.00,5.8h / 0.0h,2007.81,0.00,0.0h / 0.0h,0.00,0.00
+5,清,3.0h / 0.0h,1128.06,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,黄先生,6.2h / 0.0h,1048.14,0.00,6.8h / 0.0h,1251.92,0.00,0.0h / 0.0h,0.00,0.00
+7,游,2.2h / 0.0h,505.46,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,葛先生,0.0h / 0.0h,0.00,0.00,14.4h / 0.0h,7500.34,0.00,0.0h / 0.0h,0.00,0.00
+9,林先生,0.0h / 0.0h,0.00,0.00,2.7h / 0.0h,499.11,0.00,0.0h / 0.0h,0.00,0.00
+10,轩哥,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,415.60,0.00,0.0h / 0.0h,0.00,0.00
+11,蔡总,0.0h / 0.0h,0.00,0.00,0.7h / 0.0h,8967.31,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_千千.md b/etl_billiards/docs/table_2025-12-19/助教详情_千千.md
new file mode 100644
index 0000000..07dd33f
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_千千.md
@@ -0,0 +1,196 @@
+# 助教详情:千千(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础77.2h,附加5.0h;客户流水¥34297.90,充值归因¥0.00;头部客户(12月)Top3:张先生、周先生、陈腾鑫。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_周周.csv b/etl_billiards/docs/table_2025-12-19/助教详情_周周.csv
new file mode 100644
index 0000000..c5ba351
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_周周.csv
@@ -0,0 +1,66 @@
+助教详情:周周(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础172.6h,附加33.0h;客户流水¥80429.10,充值归因¥20000.00;头部客户(12月)Top3:周周、明哥、T。
+
+一、基础课业绩
+说明:评价:基础172.6h,附加33.0h;客户流水¥80429.10,充值归因¥20000.00;头部客户(12月)Top3:周周、明哥、T。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,41.33h,9,-3.08h,4.81h
+11月,71.27h,10,16.79h,32.38h
+12月,60.02h,6,15.21h,18.92h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,25.00h,1,16.20h,18.00h
+12月,8.00h,5,-2.27h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,27375.91,11,-1903.62,-3273.92
+11月,31436.74,15,-12817.65,-1889.58
+12月,21616.45,7,885.92,7975.80
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,11000.00,9,-3466.67,-2000.00
+11月,9000.00,4,1230.77,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,周周,28.8h / 8.0h,8105.19,0.00,0.0h / 20.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+2,明哥,0.4h / 0.0h,4190.45,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,T,10.1h / 0.0h,2968.13,0.00,0.0h / 0.0h,0.00,0.00,4.5h / 0.0h,1300.23,0.00
+4,大G,14.8h / 0.0h,2724.15,0.00,2.8h / 0.0h,1783.61,0.00,0.0h / 0.0h,0.00,0.00
+5,罗先生,2.6h / 0.0h,1584.22,0.00,9.0h / 0.0h,2415.09,0.00,0.0h / 0.0h,0.00,0.00
+6,游,2.4h / 0.0h,1307.16,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,张先生,0.0h / 0.0h,449.03,0.00,6.3h / 0.0h,2092.46,0.00,4.1h / 0.0h,1650.08,0.00
+8,轩哥,0.7h / 0.0h,288.12,0.00,5.0h / 3.0h,2175.94,5000.00,20.2h / 0.0h,16154.38,10000.00
+9,江先生,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,3588.88,0.00,0.0h / 0.0h,0.00,0.00
+10,罗超杰,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,255.63,0.00,0.0h / 0.0h,0.00,0.00
+11,陈腾鑫,0.0h / 0.0h,0.00,0.00,4.6h / 0.0h,1210.78,0.00,0.0h / 0.0h,197.60,1000.00
+12,林总,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,439.96,0.00,0.0h / 0.0h,0.00,0.00
+13,林先生,0.0h / 0.0h,0.00,0.00,0.7h / 0.0h,747.44,0.00,0.0h / 0.0h,0.00,0.00
+14,葛先生,0.0h / 0.0h,0.00,0.00,11.0h / 0.0h,3073.27,0.00,0.0h / 0.0h,0.00,0.00
+15,羊,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,602.50,0.00,0.0h / 0.0h,0.00,0.00
+16,小熊,0.0h / 0.0h,0.00,0.00,10.7h / 0.0h,2612.37,4000.00,0.0h / 0.0h,0.00,0.00
+17,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,5714.01,0.00
+18,蔡总,0.0h / 0.0h,0.00,0.00,8.2h / 0.0h,9385.22,0.00,0.0h / 0.0h,0.00,0.00
+19,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 2.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+20,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.7h / 0.0h,1080.89,0.00
+21,林先生,0.0h / 0.0h,0.00,0.00,4.0h / 0.0h,1053.59,0.00,0.0h / 0.0h,0.00,0.00
+22,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.4h / 0.0h,1278.72,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_周周.md b/etl_billiards/docs/table_2025-12-19/助教详情_周周.md
new file mode 100644
index 0000000..68ef417
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_周周.md
@@ -0,0 +1,196 @@
+# 助教详情:周周(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础172.6h,附加33.0h;客户流水¥80429.10,充值归因¥20000.00;头部客户(12月)Top3:周周、明哥、T。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_奈千.csv b/etl_billiards/docs/table_2025-12-19/助教详情_奈千.csv
new file mode 100644
index 0000000..55b648d
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_奈千.csv
@@ -0,0 +1,58 @@
+助教详情:奈千(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础59.0h,附加0.0h;客户流水¥107484.78,充值归因¥18000.00;头部客户(12月)Top3:轩哥、黎先生、陈先生。
+
+一、基础课业绩
+说明:评价:基础59.0h,附加0.0h;客户流水¥107484.78,充值归因¥18000.00;头部客户(12月)Top3:轩哥、黎先生、陈先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,23.62h,13,-20.79h,-12.91h
+11月,32.83h,19,-21.64h,-6.05h
+12月,2.58h,21,-42.23h,-38.51h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,38653.58,7,9374.05,8003.75
+11月,68543.08,7,24288.69,35216.76
+12月,288.12,22,-20442.41,-13352.52
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,18000.00,6,3533.33,5000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,轩哥,0.7h / 0.0h,288.12,0.00,4.3h / 0.0h,14349.45,0.00,6.2h / 0.0h,22341.76,13000.00
+2,黎先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.7h / 0.0h,470.19,0.00
+3,陈先生,0.0h / 0.0h,0.00,0.00,5.1h / 0.0h,1150.83,0.00,0.0h / 0.0h,0.00,0.00
+4,羊,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,3620.75,0.00
+5,陈腾鑫,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,441.39,0.00,2.1h / 0.0h,1084.69,1000.00
+6,张先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,474.93,0.00
+7,夏,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,2595.54,1000.00
+8,罗超,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.5h / 0.0h,1013.51,0.00
+9,罗先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,1143.87,3000.00
+10,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.4h / 0.0h,5714.01,0.00
+11,阿亮,0.0h / 0.0h,0.00,0.00,2.9h / 0.0h,493.02,0.00,0.0h / 0.0h,0.00,0.00
+12,曾先生,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,206.16,0.00,0.0h / 0.0h,0.00,0.00
+13,蔡总,1.8h / 0.0h,0.00,0.00,17.0h / 0.0h,51902.23,0.00,0.0h / 0.0h,0.00,0.00
+14,T,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,194.33,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_奈千.md b/etl_billiards/docs/table_2025-12-19/助教详情_奈千.md
new file mode 100644
index 0000000..25e397f
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_奈千.md
@@ -0,0 +1,196 @@
+# 助教详情:奈千(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础59.0h,附加0.0h;客户流水¥107484.78,充值归因¥18000.00;头部客户(12月)Top3:轩哥、黎先生、陈先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.csv b/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.csv
new file mode 100644
index 0000000..c91de92
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.csv
@@ -0,0 +1,46 @@
+助教详情:姜姜(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础6.6h,附加3.0h;客户流水¥2333.94,充值归因¥4000.00;头部客户(12月)Top3:罗先生、汪先生。
+
+一、基础课业绩
+说明:评价:基础6.6h,附加3.0h;客户流水¥2333.94,充值归因¥4000.00;头部客户(12月)Top3:罗先生、汪先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,6.60h,18,-37.81h,-29.93h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,3.00h,5,-3.57h,-5.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,2333.94,20,-26945.59,-28315.89
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,4000.00,12,-10466.67,-9000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,罗先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.5h / 0.0h,1143.87,3000.00
+2,汪先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,5.1h / 3.0h,1190.07,1000.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.md b/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.md
new file mode 100644
index 0000000..3b5c045
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_姜姜.md
@@ -0,0 +1,196 @@
+# 助教详情:姜姜(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础6.6h,附加3.0h;客户流水¥2333.94,充值归因¥4000.00;头部客户(12月)Top3:罗先生、汪先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.csv b/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.csv
new file mode 100644
index 0000000..ece6ca8
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.csv
@@ -0,0 +1,65 @@
+助教详情:婉婉(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础154.6h,附加34.0h;客户流水¥106476.37,充值归因¥33000.00;头部客户(12月)Top3:江先生、明哥、候。
+
+一、基础课业绩
+说明:评价:基础154.6h,附加34.0h;客户流水¥106476.37,充值归因¥33000.00;头部客户(12月)Top3:江先生、明哥、候。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,90.68h,3,46.27h,54.16h
+11月,46.03h,12,-8.44h,7.15h
+12月,17.83h,17,-26.98h,-23.26h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,4.00h,4,-2.57h,-4.00h
+11月,15.00h,2,6.20h,8.00h
+12月,15.00h,3,4.73h,7.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,62187.64,2,32908.11,31537.81
+11月,33326.32,14,-10928.07,0.00
+12月,10962.41,15,-9768.12,-2678.24
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,24000.00,4,9533.33,11000.00
+11月,9000.00,4,1230.77,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,江先生,4.7h / 0.0h,5889.30,0.00,9.4h / 0.0h,6947.07,5000.00,2.7h / 0.0h,1538.09,0.00
+2,明哥,11.7h / 10.0h,4822.90,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,候,1.1h / 0.0h,195.75,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,刘哥,0.3h / 0.0h,54.46,0.00,5.0h / 0.0h,2982.34,0.00,0.0h / 0.0h,0.00,0.00
+5,林总,0.0h / 0.0h,0.00,0.00,0.9h / 0.0h,244.48,0.00,0.0h / 0.0h,0.00,0.00
+6,羊,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,3620.75,0.00
+7,叶先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.7h / 0.0h,1278.01,0.00
+8,邓飛,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,925.47,1000.00,0.0h / 4.0h,0.00,0.00
+9,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,6.7h / 0.0h,4718.40,0.00
+10,夏,0.0h / 0.0h,0.00,0.00,5.4h / 4.0h,2991.13,0.00,18.2h / 0.0h,11826.32,1000.00
+11,轩哥,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,45.2h / 0.0h,33043.15,16000.00
+12,罗先生,0.0h / 5.0h,0.00,0.00,7.9h / 0.0h,2086.94,0.00,3.4h / 0.0h,1143.87,3000.00
+13,蔡总,0.0h / 0.0h,0.00,0.00,0.0h / 3.0h,6196.43,0.00,0.0h / 0.0h,0.00,0.00
+14,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,3924.18,3000.00
+15,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 4.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+16,老宋,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,465.98,0.00,0.0h / 0.0h,0.00,0.00
+17,黎先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,470.19,0.00
+18,君姐,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,1864.86,0.00,0.0h / 0.0h,0.00,0.00
+19,林先生,0.0h / 0.0h,0.00,0.00,6.0h / 4.0h,2690.52,0.00,0.0h / 0.0h,0.00,0.00
+20,婉婉,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,242.81,0.00,2.8h / 0.0h,624.68,1000.00
+21,胡先生,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,5688.29,3000.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.md b/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.md
new file mode 100644
index 0000000..09efb40
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_婉婉.md
@@ -0,0 +1,196 @@
+# 助教详情:婉婉(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础154.6h,附加34.0h;客户流水¥106476.37,充值归因¥33000.00;头部客户(12月)Top3:江先生、明哥、候。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小侯.csv b/etl_billiards/docs/table_2025-12-19/助教详情_小侯.csv
new file mode 100644
index 0000000..27942ed
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小侯.csv
@@ -0,0 +1,57 @@
+助教详情:小侯(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础92.2h,附加0.0h;客户流水¥41280.98,充值归因¥0.00;头部客户(12月)Top3:张先生、陈腾鑫、李先生。
+
+一、基础课业绩
+说明:评价:基础92.2h,附加0.0h;客户流水¥41280.98,充值归因¥0.00;头部客户(12月)Top3:张先生、陈腾鑫、李先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,42.58h,13,-11.89h,3.70h
+12月,49.57h,8,4.76h,8.47h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,27313.21,16,-16941.18,-6013.11
+12月,13967.77,11,-6762.76,327.12
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,张先生,14.4h / 0.0h,4161.57,0.00,5.8h / 0.0h,1583.86,0.00,0.0h / 0.0h,0.00,0.00
+2,陈腾鑫,12.1h / 0.0h,3984.45,0.00,7.0h / 0.0h,2965.62,0.00,0.0h / 0.0h,0.00,0.00
+3,李先生,9.3h / 0.0h,1729.57,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,梅,3.3h / 0.0h,1356.34,0.00,1.4h / 0.0h,1573.10,0.00,0.0h / 0.0h,0.00,0.00
+5,清,3.0h / 0.0h,1128.06,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,T,3.9h / 0.0h,938.16,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,候,3.4h / 0.0h,669.62,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,林志铭,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,220.15,0.00,0.0h / 0.0h,0.00,0.00
+9,林先生,0.0h / 0.0h,0.00,0.00,9.7h / 0.0h,3619.37,0.00,0.0h / 0.0h,0.00,0.00
+10,艾宇民,0.0h / 0.0h,0.00,0.00,7.6h / 0.0h,3872.24,0.00,0.0h / 0.0h,0.00,0.00
+11,蔡总,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,10419.30,0.00,0.0h / 0.0h,0.00,0.00
+12,钟智豪,0.0h / 0.0h,0.00,0.00,1.8h / 0.0h,274.34,0.00,0.0h / 0.0h,0.00,0.00
+13,李先生,0.0h / 0.0h,0.00,0.00,5.6h / 0.0h,2785.23,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小侯.md b/etl_billiards/docs/table_2025-12-19/助教详情_小侯.md
new file mode 100644
index 0000000..b71681b
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小侯.md
@@ -0,0 +1,196 @@
+# 助教详情:小侯(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础92.2h,附加0.0h;客户流水¥41280.98,充值归因¥0.00;头部客户(12月)Top3:张先生、陈腾鑫、李先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小敌.csv b/etl_billiards/docs/table_2025-12-19/助教详情_小敌.csv
new file mode 100644
index 0000000..659a0d4
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小敌.csv
@@ -0,0 +1,55 @@
+助教详情:小敌(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础135.1h,附加3.0h;客户流水¥93760.82,充值归因¥29000.00;头部客户(12月)Top3:郑先生、张先生、轩哥。
+
+一、基础课业绩
+说明:评价:基础135.1h,附加3.0h;客户流水¥93760.82,充值归因¥29000.00;头部客户(12月)Top3:郑先生、张先生、轩哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,55.82h,7,11.41h,19.29h
+11月,72.90h,9,18.42h,34.02h
+12月,6.40h,20,-38.41h,-34.69h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,3.00h,5,-3.57h,-5.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,44510.29,4,15230.76,13860.46
+11月,47986.57,9,3732.18,14660.25
+12月,1263.96,20,-19466.57,-12376.68
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,21000.00,5,6533.33,8000.00
+11月,8000.00,5,230.77,-1000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,郑先生,4.9h / 0.0h,814.93,0.00,27.3h / 0.0h,4745.90,0.00,0.0h / 0.0h,0.00,0.00
+2,张先生,1.5h / 0.0h,449.03,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,轩哥,0.0h / 0.0h,0.00,0.00,11.2h / 0.0h,15962.93,0.00,43.1h / 0.0h,32148.10,21000.00
+4,游,0.0h / 0.0h,0.00,0.00,3.6h / 0.0h,3791.20,0.00,0.0h / 0.0h,0.00,0.00
+5,叶先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.1h / 0.0h,3922.17,0.00
+6,李先生,0.0h / 0.0h,0.00,0.00,11.8h / 0.0h,2997.53,3000.00,0.0h / 0.0h,0.00,0.00
+7,周先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,6.6h / 0.0h,2726.01,0.00
+8,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.0h / 0.0h,5714.01,0.00
+9,蔡总,0.0h / 0.0h,0.00,0.00,17.2h / 0.0h,19881.95,5000.00,0.0h / 0.0h,0.00,0.00
+10,林先生,0.0h / 0.0h,0.00,0.00,1.9h / 0.0h,607.06,0.00,0.0h / 0.0h,0.00,0.00
+11,邓飛,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 3.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小敌.md b/etl_billiards/docs/table_2025-12-19/助教详情_小敌.md
new file mode 100644
index 0000000..e1078be
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小敌.md
@@ -0,0 +1,196 @@
+# 助教详情:小敌(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础135.1h,附加3.0h;客户流水¥93760.82,充值归因¥29000.00;头部客户(12月)Top3:郑先生、张先生、轩哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小柔.csv b/etl_billiards/docs/table_2025-12-19/助教详情_小柔.csv
new file mode 100644
index 0000000..384edcd
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小柔.csv
@@ -0,0 +1,66 @@
+助教详情:小柔(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础207.4h,附加22.0h;客户流水¥209918.77,充值归因¥42700.00;头部客户(12月)Top3:蔡总、轩哥、明哥。
+
+一、基础课业绩
+说明:评价:基础207.4h,附加22.0h;客户流水¥209918.77,充值归因¥42700.00;头部客户(12月)Top3:蔡总、轩哥、明哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,63.87h,5,19.46h,27.34h
+11月,88.65h,6,34.17h,49.77h
+12月,54.93h,7,10.12h,13.84h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,7.00h,4,-1.80h,0.00h
+12月,15.00h,3,4.73h,7.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,52623.85,3,23344.32,21974.02
+11月,110137.94,3,65883.55,76811.62
+12月,47156.98,3,26426.45,33516.34
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,31700.00,2,17233.33,18700.00
+11月,11000.00,2,3230.77,2000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,蔡总,30.2h / 0.0h,25658.77,0.00,62.2h / 3.0h,88451.79,5000.00,0.0h / 0.0h,0.00,0.00
+2,轩哥,8.4h / 0.0h,13202.16,0.00,2.0h / 0.0h,4130.37,0.00,35.2h / 0.0h,33211.31,23000.00
+3,明哥,7.7h / 12.0h,4190.45,0.00,5.8h / 0.0h,2258.14,0.00,0.0h / 0.0h,0.00,0.00
+4,江先生,3.2h / 0.0h,3042.99,0.00,6.1h / 0.0h,7578.00,5000.00,2.7h / 0.0h,1538.09,0.00
+5,T,2.0h / 0.0h,434.21,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,昌哥,1.8h / 0.0h,318.40,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,陈腾鑫,1.6h / 0.0h,310.00,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,罗先生,0.0h / 0.0h,0.00,0.00,4.1h / 0.0h,722.25,0.00,0.0h / 0.0h,0.00,0.00
+9,邓飛,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,925.47,1000.00,0.0h / 0.0h,0.00,0.00
+10,吴生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,685.89,0.00
+11,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,2789.21,0.00
+12,羊,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,383.40,0.00,0.0h / 0.0h,0.00,0.00
+13,张先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.3h / 0.0h,568.87,0.00
+14,游,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,935.84,0.00,0.0h / 0.0h,0.00,0.00
+15,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.0h / 0.0h,5714.01,0.00
+16,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,7.5h / 0.0h,2750.70,3000.00
+17,罗先生,0.0h / 3.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+18,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 4.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+19,林先生,0.0h / 0.0h,0.00,0.00,3.2h / 0.0h,2398.29,0.00,0.0h / 0.0h,0.00,0.00
+20,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.7h / 0.0h,362.17,0.00
+21,叶总,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,5003.60,5700.00
+22,胡先生,0.0h / 0.0h,0.00,0.00,0.1h / 0.0h,2354.39,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小柔.md b/etl_billiards/docs/table_2025-12-19/助教详情_小柔.md
new file mode 100644
index 0000000..9247805
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小柔.md
@@ -0,0 +1,196 @@
+# 助教详情:小柔(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础207.4h,附加22.0h;客户流水¥209918.77,充值归因¥42700.00;头部客户(12月)Top3:蔡总、轩哥、明哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小柳.csv b/etl_billiards/docs/table_2025-12-19/助教详情_小柳.csv
new file mode 100644
index 0000000..0a44a03
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小柳.csv
@@ -0,0 +1,44 @@
+助教详情:小柳(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+一、基础课业绩
+说明:评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小柳.md b/etl_billiards/docs/table_2025-12-19/助教详情_小柳.md
new file mode 100644
index 0000000..8872c16
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小柳.md
@@ -0,0 +1,196 @@
+# 助教详情:小柳(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小燕.csv b/etl_billiards/docs/table_2025-12-19/助教详情_小燕.csv
new file mode 100644
index 0000000..eca0b93
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小燕.csv
@@ -0,0 +1,48 @@
+助教详情:小燕(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础268.3h,附加23.0h;客户流水¥77172.28,充值归因¥0.00;头部客户(12月)Top3:葛先生、小燕、梅。
+
+一、基础课业绩
+说明:评价:基础268.3h,附加23.0h;客户流水¥77172.28,充值归因¥0.00;头部客户(12月)Top3:葛先生、小燕、梅。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,109.28h,3,54.81h,70.40h
+12月,159.02h,1,114.21h,117.92h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,2.00h,6,-6.80h,-5.00h
+12月,21.00h,2,10.73h,13.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,39426.42,12,-4827.97,6100.10
+12月,37745.86,5,17015.33,24105.22
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,葛先生,80.8h / 16.0h,22323.38,0.00,53.5h / 0.0h,17941.19,0.00,0.0h / 0.0h,0.00,0.00
+2,小燕,78.2h / 5.0h,15422.48,0.00,51.4h / 2.0h,10944.82,0.00,0.0h / 0.0h,0.00,0.00
+3,梅,0.0h / 0.0h,0.00,0.00,3.8h / 0.0h,1573.10,0.00,0.0h / 0.0h,0.00,0.00
+4,蔡总,0.0h / 0.0h,0.00,0.00,0.7h / 0.0h,8967.31,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_小燕.md b/etl_billiards/docs/table_2025-12-19/助教详情_小燕.md
new file mode 100644
index 0000000..af5c276
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_小燕.md
@@ -0,0 +1,196 @@
+# 助教详情:小燕(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础268.3h,附加23.0h;客户流水¥77172.28,充值归因¥0.00;头部客户(12月)Top3:葛先生、小燕、梅。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_希希.csv b/etl_billiards/docs/table_2025-12-19/助教详情_希希.csv
new file mode 100644
index 0000000..bc73ed6
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_希希.csv
@@ -0,0 +1,47 @@
+助教详情:希希(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础6.6h,附加0.0h;客户流水¥3367.56,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、歌神、郭先生。
+
+一、基础课业绩
+说明:评价:基础6.6h,附加0.0h;客户流水¥3367.56,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、歌神、郭先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,5.02h,19,-39.39h,-31.51h
+11月,1.58h,27,-52.89h,-37.30h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,3086.34,18,-26193.19,-27563.49
+11月,281.22,27,-43973.17,-33045.10
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,陈腾鑫,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,359.28,0.00
+2,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.0h / 0.0h,2727.06,0.00
+3,郭先生,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,281.22,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_希希.md b/etl_billiards/docs/table_2025-12-19/助教详情_希希.md
new file mode 100644
index 0000000..7a68a55
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_希希.md
@@ -0,0 +1,196 @@
+# 助教详情:希希(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础6.6h,附加0.0h;客户流水¥3367.56,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、歌神、郭先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_年糕.csv b/etl_billiards/docs/table_2025-12-19/助教详情_年糕.csv
new file mode 100644
index 0000000..e37cfbe
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_年糕.csv
@@ -0,0 +1,63 @@
+助教详情:年糕(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础82.6h,附加7.0h;客户流水¥59830.16,充值归因¥9000.00;头部客户(12月)Top3:葛先生、明哥、蔡总。
+
+一、基础课业绩
+说明:评价:基础82.6h,附加7.0h;客户流水¥59830.16,充值归因¥9000.00;头部客户(12月)Top3:葛先生、明哥、蔡总。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,21.23h,14,-23.18h,-15.29h
+11月,35.80h,15,-18.68h,-3.08h
+12月,25.62h,14,-19.19h,-15.48h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,7.00h,4,-1.80h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,26289.89,12,-2989.64,-4359.94
+11月,15696.08,20,-28558.31,-17630.24
+12月,17844.19,9,-2886.34,4203.54
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,9000.00,10,-5466.67,-4000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,葛先生,2.6h / 0.0h,5551.79,0.00,6.7h / 0.0h,3777.09,0.00,0.0h / 0.0h,0.00,0.00
+2,明哥,4.6h / 0.0h,4190.45,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,蔡总,6.0h / 0.0h,2130.39,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,叶先生,2.6h / 0.0h,1558.40,0.00,1.8h / 0.0h,711.79,0.00,5.3h / 0.0h,3607.02,3000.00
+5,君姐,2.2h / 0.0h,1414.23,0.00,6.0h / 0.0h,1864.86,0.00,0.0h / 0.0h,0.00,0.00
+6,林先生,0.9h / 0.0h,1369.51,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,张先生,2.5h / 0.0h,540.07,0.00,4.2h / 0.0h,1007.52,0.00,2.1h / 0.0h,596.24,0.00
+8,潘先生,2.0h / 0.0h,516.93,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+9,常总,1.7h / 0.0h,460.52,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+10,小燕,0.5h / 0.0h,111.90,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+11,谢俊,0.0h / 0.0h,0.00,0.00,4.5h / 0.0h,794.53,0.00,0.0h / 0.0h,0.00,0.00
+12,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,1929.19,0.00
+13,夏,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.2h / 0.0h,4670.88,0.00
+14,轩哥,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,7.2h / 0.0h,12643.27,3000.00
+15,罗先生,0.0h / 0.0h,0.00,0.00,7.6h / 0.0h,2400.67,0.00,0.0h / 0.0h,0.00,0.00
+16,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,2843.29,3000.00
+17,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 7.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+18,胡先生,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,2354.39,0.00,0.0h / 0.0h,0.00,0.00
+19,李先生,0.0h / 0.0h,0.00,0.00,4.2h / 0.0h,2785.23,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_年糕.md b/etl_billiards/docs/table_2025-12-19/助教详情_年糕.md
new file mode 100644
index 0000000..6d5df8b
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_年糕.md
@@ -0,0 +1,196 @@
+# 助教详情:年糕(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础82.6h,附加7.0h;客户流水¥59830.16,充值归因¥9000.00;头部客户(12月)Top3:葛先生、明哥、蔡总。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.csv b/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.csv
new file mode 100644
index 0000000..4787f35
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.csv
@@ -0,0 +1,46 @@
+助教详情:悦悦(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础2.3h,附加0.0h;客户流水¥2970.96,充值归因¥3000.00;头部客户(12月)Top3:小宇、轩哥。
+
+一、基础课业绩
+说明:评价:基础2.3h,附加0.0h;客户流水¥2970.96,充值归因¥3000.00;头部客户(12月)Top3:小宇、轩哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,2.30h,20,-42.11h,-34.23h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,2970.96,19,-26308.57,-27678.87
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,3000.00,13,-11466.67,-10000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,小宇,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.4h / 0.0h,78.52,0.00
+2,轩哥,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.9h / 0.0h,2892.44,3000.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.md b/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.md
new file mode 100644
index 0000000..ef5b8b0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_悦悦.md
@@ -0,0 +1,196 @@
+# 助教详情:悦悦(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础2.3h,附加0.0h;客户流水¥2970.96,充值归因¥3000.00;头部客户(12月)Top3:小宇、轩哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_柚子.csv b/etl_billiards/docs/table_2025-12-19/助教详情_柚子.csv
new file mode 100644
index 0000000..546d754
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_柚子.csv
@@ -0,0 +1,56 @@
+助教详情:柚子(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础35.4h,附加10.0h;客户流水¥23234.98,充值归因¥3000.00;头部客户(12月)Top3:陈先生、羊、葛先生。
+
+一、基础课业绩
+说明:评价:基础35.4h,附加10.0h;客户流水¥23234.98,充值归因¥3000.00;头部客户(12月)Top3:陈先生、羊、葛先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,35.40h,16,-19.08h,-3.48h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,10.00h,3,1.20h,3.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,23234.98,18,-21019.41,-10091.34
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,3000.00,8,-4769.23,-6000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,陈先生,0.0h / 0.0h,0.00,0.00,4.4h / 0.0h,1150.83,0.00,0.0h / 0.0h,0.00,0.00
+2,羊,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,429.33,0.00,0.0h / 0.0h,0.00,0.00
+3,葛先生,0.0h / 0.0h,0.00,0.00,3.4h / 0.0h,3052.28,0.00,0.0h / 0.0h,0.00,0.00
+4,陈腾鑫,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,472.03,0.00,0.0h / 0.0h,0.00,0.00
+5,张先生,0.0h / 0.0h,0.00,0.00,3.2h / 0.0h,941.37,0.00,0.0h / 0.0h,0.00,0.00
+6,夏,0.0h / 0.0h,0.00,0.00,0.2h / 7.0h,2991.13,0.00,0.0h / 0.0h,0.00,0.00
+7,轩哥,0.0h / 0.0h,0.00,0.00,0.2h / 0.0h,4484.68,0.00,0.0h / 0.0h,0.00,0.00
+8,胡先生,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,5688.29,3000.00,0.0h / 0.0h,0.00,0.00
+9,李先生,0.0h / 0.0h,0.00,0.00,7.8h / 0.0h,1712.78,0.00,0.0h / 0.0h,0.00,0.00
+10,牛先生,0.0h / 0.0h,0.00,0.00,10.4h / 0.0h,1887.48,0.00,0.0h / 0.0h,0.00,0.00
+11,阿亮,0.0h / 0.0h,0.00,0.00,2.4h / 0.0h,424.78,0.00,0.0h / 0.0h,0.00,0.00
+12,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 3.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_柚子.md b/etl_billiards/docs/table_2025-12-19/助教详情_柚子.md
new file mode 100644
index 0000000..15b80ae
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_柚子.md
@@ -0,0 +1,196 @@
+# 助教详情:柚子(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础35.4h,附加10.0h;客户流水¥23234.98,充值归因¥3000.00;头部客户(12月)Top3:陈先生、羊、葛先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.csv b/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.csv
new file mode 100644
index 0000000..068ad17
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.csv
@@ -0,0 +1,51 @@
+助教详情:梦梦(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础35.7h,附加1.0h;客户流水¥45991.89,充值归因¥0.00;头部客户(12月)Top3:葛先生、阿亮、蔡总。
+
+一、基础课业绩
+说明:评价:基础35.7h,附加1.0h;客户流水¥45991.89,充值归因¥0.00;头部客户(12月)Top3:葛先生、阿亮、蔡总。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,19.60h,22,-34.88h,-19.28h
+12月,16.08h,18,-28.73h,-25.01h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,1.00h,7,-7.80h,-6.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,39768.09,11,-4486.30,6441.77
+12月,6223.80,18,-14506.73,-7416.84
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,葛先生,2.9h / 0.0h,5551.79,0.00,4.4h / 0.0h,1884.66,0.00,0.0h / 0.0h,0.00,0.00
+2,阿亮,2.7h / 0.0h,495.46,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,蔡总,10.5h / 0.0h,176.55,0.00,7.0h / 1.0h,34274.25,0.00,0.0h / 0.0h,0.00,0.00
+4,轩哥,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,363.25,0.00,0.0h / 0.0h,0.00,0.00
+5,羊,0.0h / 0.0h,0.00,0.00,0.6h / 0.0h,104.77,0.00,0.0h / 0.0h,0.00,0.00
+6,林先生,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,2461.85,0.00,0.0h / 0.0h,0.00,0.00
+7,张先生,0.0h / 0.0h,0.00,0.00,2.3h / 0.0h,679.31,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.md b/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.md
new file mode 100644
index 0000000..0068571
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_梦梦.md
@@ -0,0 +1,196 @@
+# 助教详情:梦梦(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础35.7h,附加1.0h;客户流水¥45991.89,充值归因¥0.00;头部客户(12月)Top3:葛先生、阿亮、蔡总。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.csv b/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.csv
new file mode 100644
index 0000000..6b3c3fa
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.csv
@@ -0,0 +1,44 @@
+助教详情:楚楚(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+一、基础课业绩
+说明:评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.md b/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.md
new file mode 100644
index 0000000..d1aacfc
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_楚楚.md
@@ -0,0 +1,196 @@
+# 助教详情:楚楚(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础0.0h,附加0.0h;客户流水¥0.00,充值归因¥0.00;头部客户(12月)Top3:无。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.csv b/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.csv
new file mode 100644
index 0000000..312e2b0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.csv
@@ -0,0 +1,52 @@
+助教详情:欣怡(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础29.8h,附加0.0h;客户流水¥9981.98,充值归因¥7000.00;头部客户(12月)Top3:老宋、张先生、轩哥。
+
+一、基础课业绩
+说明:评价:基础29.8h,附加0.0h;客户流水¥9981.98,充值归因¥7000.00;头部客户(12月)Top3:老宋、张先生、轩哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,19.50h,15,-24.91h,-17.03h
+11月,10.33h,24,-44.14h,-28.55h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,4824.69,17,-24454.84,-25825.14
+11月,5157.29,24,-39097.10,-28169.03
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,3000.00,13,-11466.67,-10000.00
+11月,4000.00,7,-3769.23,-5000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,老宋,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.5h / 0.0h,75.99,0.00
+2,张先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.4h / 0.0h,570.76,0.00
+3,轩哥,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,408.24,0.00
+4,羊,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,364.70,0.00,0.0h / 0.0h,0.00,0.00
+5,小熊,0.0h / 0.0h,0.00,0.00,7.8h / 0.0h,2438.20,4000.00,0.0h / 0.0h,0.00,0.00
+6,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.9h / 0.0h,904.50,0.00
+7,T,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,10.3h / 0.0h,2865.20,3000.00
+8,胡先生,0.0h / 0.0h,0.00,0.00,0.4h / 0.0h,2354.39,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.md b/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.md
new file mode 100644
index 0000000..55c8a47
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_欣怡.md
@@ -0,0 +1,196 @@
+# 助教详情:欣怡(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础29.8h,附加0.0h;客户流水¥9981.98,充值归因¥7000.00;头部客户(12月)Top3:老宋、张先生、轩哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.csv b/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.csv
new file mode 100644
index 0000000..29e1380
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.csv
@@ -0,0 +1,48 @@
+助教详情:泡芙(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础21.4h,附加3.0h;客户流水¥8323.03,充值归因¥0.00;头部客户(12月)Top3:夏、艾宇民、羊。
+
+一、基础课业绩
+说明:评价:基础21.4h,附加3.0h;客户流水¥8323.03,充值归因¥0.00;头部客户(12月)Top3:夏、艾宇民、羊。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,21.38h,21,-33.09h,-17.50h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,3.00h,5,-5.80h,-4.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,8323.03,23,-35931.36,-25003.29
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,夏,0.0h / 0.0h,0.00,0.00,2.4h / 0.0h,501.87,0.00,0.0h / 0.0h,0.00,0.00
+2,艾宇民,0.0h / 0.0h,0.00,0.00,17.5h / 3.0h,5037.44,0.00,0.0h / 0.0h,0.00,0.00
+3,羊,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,429.33,0.00,0.0h / 0.0h,0.00,0.00
+4,胡先生,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,2354.39,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.md b/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.md
new file mode 100644
index 0000000..f47a20a
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_泡芙.md
@@ -0,0 +1,196 @@
+# 助教详情:泡芙(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础21.4h,附加3.0h;客户流水¥8323.03,充值归因¥0.00;头部客户(12月)Top3:夏、艾宇民、羊。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.csv b/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.csv
new file mode 100644
index 0000000..e365ba9
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.csv
@@ -0,0 +1,60 @@
+助教详情:涛涛(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础168.6h,附加3.0h;客户流水¥166962.41,充值归因¥26000.00;头部客户(12月)Top3:蔡总、轩哥、葛先生。
+
+一、基础课业绩
+说明:评价:基础168.6h,附加3.0h;客户流水¥166962.41,充值归因¥26000.00;头部客户(12月)Top3:蔡总、轩哥、葛先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,50.13h,8,5.72h,13.61h
+11月,74.40h,7,19.92h,35.52h
+12月,44.08h,10,-0.73h,2.99h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,3.00h,5,-5.80h,-4.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,35940.84,8,6661.31,5291.01
+11月,88677.55,4,44423.16,55351.23
+12月,42344.02,4,21613.49,28703.38
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,21000.00,5,6533.33,8000.00
+11月,5000.00,6,-2769.23,-4000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,蔡总,15.1h / 0.0h,18914.63,0.00,28.4h / 0.0h,57785.21,0.00,0.0h / 0.0h,0.00,0.00
+2,轩哥,10.8h / 0.0h,14490.25,0.00,21.8h / 0.0h,22186.78,0.00,40.1h / 0.0h,30415.18,15000.00
+3,葛先生,5.8h / 0.0h,5551.79,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,君姐,2.2h / 0.0h,1414.23,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+5,候,3.1h / 0.0h,563.70,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,阿亮,2.9h / 0.0h,538.07,0.00,1.7h / 3.0h,300.53,0.00,0.0h / 0.0h,0.00,0.00
+7,罗先生,2.3h / 0.0h,524.41,0.00,2.3h / 0.0h,844.76,0.00,6.0h / 0.0h,1773.80,3000.00
+8,张先生,1.9h / 0.0h,346.94,0.00,1.8h / 0.0h,325.27,0.00,0.0h / 0.0h,0.00,0.00
+9,江先生,0.0h / 0.0h,0.00,0.00,1.8h / 0.0h,2095.41,5000.00,0.0h / 0.0h,0.00,0.00
+10,叶先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.1h / 0.0h,3607.02,3000.00
+11,吴生,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,537.96,0.00,0.0h / 0.0h,0.00,0.00
+12,陈淑涛,0.0h / 0.0h,0.00,0.00,4.4h / 0.0h,1176.77,0.00,0.0h / 0.0h,0.00,0.00
+13,李先生,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,779.48,0.00,0.0h / 0.0h,0.00,0.00
+14,明哥,0.0h / 0.0h,0.00,0.00,5.4h / 0.0h,2258.14,0.00,0.0h / 0.0h,0.00,0.00
+15,冯先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.9h / 0.0h,144.84,0.00
+16,胡先生,0.0h / 0.0h,0.00,0.00,2.7h / 0.0h,387.24,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.md b/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.md
new file mode 100644
index 0000000..cc57443
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_涛涛.md
@@ -0,0 +1,196 @@
+# 助教详情:涛涛(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础168.6h,附加3.0h;客户流水¥166962.41,充值归因¥26000.00;头部客户(12月)Top3:蔡总、轩哥、葛先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_球球.csv b/etl_billiards/docs/table_2025-12-19/助教详情_球球.csv
new file mode 100644
index 0000000..ae1ce76
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_球球.csv
@@ -0,0 +1,74 @@
+助教详情:球球(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础172.5h,附加41.0h;客户流水¥95647.82,充值归因¥24000.00;头部客户(12月)Top3:葛先生、周周、T。
+
+一、基础课业绩
+说明:评价:基础172.5h,附加41.0h;客户流水¥95647.82,充值归因¥24000.00;头部客户(12月)Top3:葛先生、周周、T。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,57.45h,6,13.04h,20.92h
+11月,66.50h,11,12.02h,27.62h
+12月,48.58h,9,3.77h,7.49h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,11.00h,1,4.43h,3.00h
+11月,25.00h,1,16.20h,18.00h
+12月,5.00h,6,-5.27h,-3.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,33923.75,10,4644.22,3273.92
+11月,41907.39,10,-2347.00,8581.07
+12月,19816.68,8,-913.85,6176.04
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,15000.00,8,533.33,2000.00
+11月,9000.00,4,1230.77,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,葛先生,1.1h / 0.0h,5551.79,0.00,0.9h / 0.0h,3052.28,0.00,0.0h / 0.0h,0.00,0.00
+2,周周,15.2h / 0.0h,4161.75,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,T,10.7h / 0.0h,3327.26,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,蔡总,8.5h / 0.0h,2130.39,0.00,3.4h / 0.0h,6196.43,0.00,0.0h / 0.0h,0.00,0.00
+5,罗先生,2.3h / 0.0h,1584.22,0.00,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,514.68,0.00
+6,候,5.3h / 0.0h,926.59,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,张先生,3.0h / 0.0h,876.46,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,李先生,0.0h / 0.0h,703.83,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+9,大G,1.8h / 0.0h,467.10,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+10,黄先生,0.6h / 5.0h,87.29,0.00,4.4h / 18.0h,828.62,0.00,11.0h / 9.0h,1608.13,0.00
+11,邓飛,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,925.47,1000.00,0.0h / 0.0h,0.00,0.00
+12,罗超杰,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,176.14,0.00
+13,陈腾鑫,0.0h / 0.0h,0.00,0.00,25.1h / 0.0h,5150.83,0.00,6.1h / 2.0h,980.14,0.00
+14,叶先生,0.0h / 0.0h,0.00,0.00,6.7h / 0.0h,3013.86,0.00,0.0h / 0.0h,0.00,0.00
+15,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,1929.19,0.00
+16,羊,0.0h / 0.0h,0.00,0.00,2.2h / 0.0h,383.40,0.00,3.1h / 0.0h,3620.75,0.00
+17,夏,0.0h / 0.0h,0.00,0.00,2.0h / 4.0h,370.12,0.00,2.5h / 0.0h,455.12,0.00
+18,轩哥,0.0h / 0.0h,0.00,0.00,11.2h / 0.0h,12063.93,5000.00,9.1h / 0.0h,9207.48,6000.00
+19,罗超,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.9h / 0.0h,2385.30,3000.00
+20,小熊,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.4h / 0.0h,709.18,0.00
+21,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.8h / 0.0h,5714.01,0.00
+22,刘哥,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,2982.34,0.00,0.0h / 0.0h,0.00,0.00
+23,桂先生,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,826.02,0.00,0.0h / 0.0h,0.00,0.00
+24,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 3.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+25,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,2843.29,3000.00
+26,胡先生,0.0h / 0.0h,0.00,0.00,3.9h / 0.0h,5688.29,3000.00,0.0h / 0.0h,0.00,0.00
+27,江先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.7h / 0.0h,2740.35,3000.00
+28,小宇,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.5h / 0.0h,318.98,0.00
+29,陶,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.7h / 0.0h,721.01,0.00
+30,小燕,0.0h / 0.0h,0.00,0.00,1.4h / 0.0h,425.80,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_球球.md b/etl_billiards/docs/table_2025-12-19/助教详情_球球.md
new file mode 100644
index 0000000..de1e3ee
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_球球.md
@@ -0,0 +1,196 @@
+# 助教详情:球球(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础172.5h,附加41.0h;客户流水¥95647.82,充值归因¥24000.00;头部客户(12月)Top3:葛先生、周周、T。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.csv b/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.csv
new file mode 100644
index 0000000..aef2879
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.csv
@@ -0,0 +1,49 @@
+助教详情:瑶瑶(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础53.7h,附加3.0h;客户流水¥72216.91,充值归因¥0.00;头部客户(12月)Top3:蔡总、轩哥、陈世。
+
+一、基础课业绩
+说明:评价:基础53.7h,附加3.0h;客户流水¥72216.91,充值归因¥0.00;头部客户(12月)Top3:蔡总、轩哥、陈世。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,34.25h,18,-20.23h,-4.63h
+12月,19.48h,15,-25.33h,-21.61h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,3.00h,5,-5.80h,-4.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,65924.36,8,21669.97,32598.04
+12月,6292.55,17,-14437.98,-7348.10
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,蔡总,19.5h / 0.0h,6292.55,0.00,20.3h / 2.0h,53735.58,0.00,0.0h / 0.0h,0.00,0.00
+2,轩哥,0.0h / 0.0h,0.00,0.00,9.3h / 1.0h,8137.22,0.00,0.0h / 0.0h,0.00,0.00
+3,陈世,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,139.15,0.00,0.0h / 0.0h,0.00,0.00
+4,游,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,3544.42,0.00,0.0h / 0.0h,0.00,0.00
+5,林先生,0.0h / 0.0h,0.00,0.00,1.9h / 0.0h,367.99,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.md b/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.md
new file mode 100644
index 0000000..5a7271b
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_瑶瑶.md
@@ -0,0 +1,196 @@
+# 助教详情:瑶瑶(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础53.7h,附加3.0h;客户流水¥72216.91,充值归因¥0.00;头部客户(12月)Top3:蔡总、轩哥、陈世。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_璇子.csv b/etl_billiards/docs/table_2025-12-19/助教详情_璇子.csv
new file mode 100644
index 0000000..cead2b0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_璇子.csv
@@ -0,0 +1,56 @@
+助教详情:璇子(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础358.9h,附加32.0h;客户流水¥301070.23,充值归因¥44700.00;头部客户(12月)Top3:轩哥、蔡总、江先生。
+
+一、基础课业绩
+说明:评价:基础358.9h,附加32.0h;客户流水¥301070.23,充值归因¥44700.00;头部客户(12月)Top3:轩哥、蔡总、江先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,120.20h,2,75.79h,83.67h
+11月,147.92h,2,93.44h,109.03h
+12月,90.75h,3,45.94h,49.66h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,8.00h,3,1.43h,0.00h
+11月,10.00h,3,1.20h,3.00h
+12月,14.00h,4,3.73h,6.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,80804.14,1,51524.61,50154.31
+11月,154486.83,1,110232.44,121160.51
+12月,65779.26,1,45048.73,52138.62
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,34700.00,1,20233.33,21700.00
+11月,10000.00,3,2230.77,1000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,轩哥,37.7h / 0.0h,28122.15,0.00,50.3h / 0.0h,46514.85,0.00,64.6h / 0.0h,53866.23,23000.00
+2,蔡总,18.3h / 0.0h,21216.97,0.00,49.9h / 0.0h,84757.28,5000.00,0.0h / 0.0h,0.00,0.00
+3,江先生,17.7h / 14.0h,10018.73,0.00,29.6h / 10.0h,14700.83,5000.00,15.2h / 8.0h,5637.50,3000.00
+4,林先生,9.6h / 0.0h,3351.61,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+5,罗先生,5.2h / 0.0h,1655.57,0.00,5.1h / 0.0h,1718.68,0.00,2.8h / 0.0h,1087.21,0.00
+6,君姐,2.2h / 0.0h,1414.23,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,游,0.0h / 0.0h,0.00,0.00,3.1h / 0.0h,3544.42,0.00,0.0h / 0.0h,0.00,0.00
+8,羊,0.0h / 0.0h,0.00,0.00,5.0h / 0.0h,1017.12,0.00,0.0h / 0.0h,0.00,0.00
+9,张先生,0.0h / 0.0h,0.00,0.00,4.9h / 0.0h,2233.65,0.00,5.4h / 0.0h,3211.91,0.00
+10,夏,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,7.6h / 0.0h,6452.71,0.00
+11,罗超,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,2385.30,3000.00
+12,叶总,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,22.0h / 0.0h,8163.28,5700.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_璇子.md b/etl_billiards/docs/table_2025-12-19/助教详情_璇子.md
new file mode 100644
index 0000000..30e4c11
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_璇子.md
@@ -0,0 +1,196 @@
+# 助教详情:璇子(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础358.9h,附加32.0h;客户流水¥301070.23,充值归因¥44700.00;头部客户(12月)Top3:轩哥、蔡总、江先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_素素.csv b/etl_billiards/docs/table_2025-12-19/助教详情_素素.csv
new file mode 100644
index 0000000..ce40957
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_素素.csv
@@ -0,0 +1,64 @@
+助教详情:素素(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础85.5h,附加10.0h;客户流水¥55755.41,充值归因¥7000.00;头部客户(12月)Top3:叶先生、周先生、轩哥。
+
+一、基础课业绩
+说明:评价:基础85.5h,附加10.0h;客户流水¥55755.41,充值归因¥7000.00;头部客户(12月)Top3:叶先生、周先生、轩哥。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,40.45h,10,-3.96h,3.92h
+11月,35.03h,17,-19.44h,-3.85h
+12月,9.98h,19,-34.83h,-31.11h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,10.00h,3,1.20h,3.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,34135.89,9,4856.36,3486.06
+11月,18707.30,19,-25547.09,-14619.02
+12月,2912.22,19,-17818.31,-10728.42
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,6000.00,11,-8466.67,-7000.00
+11月,1000.00,9,-6769.23,-8000.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,叶先生,3.0h / 0.0h,1558.40,0.00,7.0h / 3.0h,3725.65,0.00,15.1h / 0.0h,8807.20,3000.00
+2,周先生,6.2h / 0.0h,1065.70,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,轩哥,0.8h / 0.0h,288.12,0.00,0.0h / 0.0h,0.00,0.00,3.6h / 0.0h,8972.50,0.00
+4,邓飛,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,925.47,1000.00,0.0h / 0.0h,0.00,0.00
+5,罗超杰,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.9h / 0.0h,396.94,0.00
+6,陈腾鑫,0.0h / 0.0h,0.00,0.00,0.4h / 0.0h,152.18,0.00,2.1h / 0.0h,542.06,0.00
+7,谢俊,0.0h / 0.0h,0.00,0.00,2.4h / 0.0h,417.75,0.00,0.0h / 0.0h,0.00,0.00
+8,罗先生,0.0h / 0.0h,0.00,0.00,4.7h / 0.0h,861.57,0.00,0.0h / 0.0h,0.00,0.00
+9,葛先生,0.0h / 0.0h,0.00,0.00,9.1h / 0.0h,4668.26,0.00,0.0h / 0.0h,0.00,0.00
+10,歌神,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,3.9h / 0.0h,2789.21,0.00
+11,羊,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,3620.75,0.00
+12,张先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,1.1h / 0.0h,449.93,0.00
+13,都先生,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,269.64,0.00,0.0h / 0.0h,0.00,0.00
+14,夏,0.0h / 0.0h,0.00,0.00,0.8h / 4.0h,2991.13,0.00,0.0h / 0.0h,0.00,0.00
+15,罗先生,0.0h / 0.0h,0.00,0.00,4.3h / 0.0h,1856.86,0.00,0.0h / 0.0h,0.00,0.00
+16,陈德韩,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,5.5h / 0.0h,5714.01,0.00
+17,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,2843.29,3000.00
+18,万先生,0.0h / 0.0h,0.00,0.00,0.0h / 3.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+19,阿亮,0.0h / 0.0h,0.00,0.00,3.1h / 0.0h,484.40,0.00,0.0h / 0.0h,0.00,0.00
+20,胡先生,0.0h / 0.0h,0.00,0.00,0.8h / 0.0h,2354.39,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_素素.md b/etl_billiards/docs/table_2025-12-19/助教详情_素素.md
new file mode 100644
index 0000000..5480ae0
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_素素.md
@@ -0,0 +1,196 @@
+# 助教详情:素素(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础85.5h,附加10.0h;客户流水¥55755.41,充值归因¥7000.00;头部客户(12月)Top3:叶先生、周先生、轩哥。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.csv b/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.csv
new file mode 100644
index 0000000..07c011a
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.csv
@@ -0,0 +1,58 @@
+助教详情:苏苏(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础82.6h,附加9.0h;客户流水¥33952.79,充值归因¥6000.00;头部客户(12月)Top3:罗先生、T、林先生。
+
+一、基础课业绩
+说明:评价:基础82.6h,附加9.0h;客户流水¥33952.79,充值归因¥6000.00;头部客户(12月)Top3:罗先生、T、林先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,25.15h,12,-19.26h,-11.38h
+11月,13.52h,23,-40.96h,-25.37h
+12月,43.90h,11,-0.91h,2.81h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,8.00h,3,1.43h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,1.00h,9,-9.27h,-7.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,11236.84,15,-18042.69,-19412.99
+11月,10254.59,22,-33999.80,-23071.73
+12月,12461.36,14,-8269.17,-1179.28
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,6000.00,11,-8466.67,-7000.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,罗先生,19.6h / 0.0h,6061.87,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+2,T,4.5h / 0.0h,1429.89,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+3,林先生,4.9h / 0.0h,1369.86,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+4,黄先生,8.1h / 1.0h,1357.90,0.00,4.0h / 0.0h,674.36,0.00,11.2h / 4.0h,1960.96,0.00
+5,张先生,3.9h / 0.0h,1163.40,0.00,0.0h / 0.0h,0.00,0.00,6.4h / 0.0h,3604.02,0.00
+6,葛先生,2.5h / 0.0h,1004.77,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,候,0.4h / 0.0h,73.67,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,罗超,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.6h / 0.0h,2385.30,3000.00
+9,罗超杰,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.1h / 0.0h,443.27,0.00
+10,蔡总,0.0h / 0.0h,0.00,0.00,4.7h / 0.0h,6557.92,0.00,0.0h / 0.0h,0.00,0.00
+11,吕先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,2.8h / 0.0h,2843.29,3000.00
+12,林先生,0.0h / 0.0h,0.00,0.00,3.1h / 0.0h,2398.29,0.00,0.0h / 0.0h,0.00,0.00
+13,邓飛,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 4.0h,0.00,0.00
+14,昌哥,0.0h / 0.0h,0.00,0.00,1.6h / 0.0h,624.02,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.md b/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.md
new file mode 100644
index 0000000..3d21174
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_苏苏.md
@@ -0,0 +1,196 @@
+# 助教详情:苏苏(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础82.6h,附加9.0h;客户流水¥33952.79,充值归因¥6000.00;头部客户(12月)Top3:罗先生、T、林先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_西子.csv b/etl_billiards/docs/table_2025-12-19/助教详情_西子.csv
new file mode 100644
index 0000000..2e02cd3
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_西子.csv
@@ -0,0 +1,45 @@
+助教详情:西子(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础1.8h,附加0.0h;客户流水¥303.51,充值归因¥0.00;头部客户(12月)Top3:张先生。
+
+一、基础课业绩
+说明:评价:基础1.8h,附加0.0h;客户流水¥303.51,充值归因¥0.00;头部客户(12月)Top3:张先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,1.82h,26,-52.66h,-37.07h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,303.51,26,-43950.88,-33022.81
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,张先生,0.0h / 0.0h,0.00,0.00,1.8h / 0.0h,303.51,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_西子.md b/etl_billiards/docs/table_2025-12-19/助教详情_西子.md
new file mode 100644
index 0000000..43e0809
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_西子.md
@@ -0,0 +1,196 @@
+# 助教详情:西子(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础1.8h,附加0.0h;客户流水¥303.51,充值归因¥0.00;头部客户(12月)Top3:张先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_阿清.csv b/etl_billiards/docs/table_2025-12-19/助教详情_阿清.csv
new file mode 100644
index 0000000..3c1cd86
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_阿清.csv
@@ -0,0 +1,55 @@
+助教详情:阿清(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础139.9h,附加0.0h;客户流水¥53805.04,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、葛先生、梅。
+
+一、基础课业绩
+说明:评价:基础139.9h,附加0.0h;客户流水¥53805.04,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、葛先生、梅。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,73.48h,8,19.01h,34.60h
+12月,66.45h,5,21.64h,25.36h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,37302.04,13,-6952.35,3975.72
+12月,16503.00,10,-4227.53,2862.36
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,陈腾鑫,34.9h / 0.0h,7428.12,0.00,44.4h / 0.0h,10029.58,0.00,0.0h / 0.0h,0.00,0.00
+2,葛先生,7.9h / 0.0h,2831.40,0.00,19.7h / 0.0h,7141.04,0.00,0.0h / 0.0h,0.00,0.00
+3,梅,7.5h / 0.0h,2086.99,0.00,3.3h / 0.0h,1573.10,0.00,0.0h / 0.0h,0.00,0.00
+4,张先生,7.2h / 0.0h,1794.40,0.00,1.0h / 0.0h,679.31,0.00,0.0h / 0.0h,0.00,0.00
+5,清,3.0h / 0.0h,1128.06,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+6,候,4.2h / 0.0h,773.51,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+7,常总,1.7h / 0.0h,460.52,0.00,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00
+8,轩哥,0.0h / 0.0h,0.00,0.00,1.0h / 0.0h,10078.85,0.00,0.0h / 0.0h,0.00,0.00
+9,黄先生,0.0h / 0.0h,0.00,0.00,0.7h / 0.0h,382.08,0.00,0.0h / 0.0h,0.00,0.00
+10,蔡总,0.0h / 0.0h,0.00,0.00,1.5h / 0.0h,6557.92,0.00,0.0h / 0.0h,0.00,0.00
+11,小燕,0.0h / 0.0h,0.00,0.00,2.0h / 0.0h,860.16,0.00,0.0h / 0.0h,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_阿清.md b/etl_billiards/docs/table_2025-12-19/助教详情_阿清.md
new file mode 100644
index 0000000..0c79f34
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_阿清.md
@@ -0,0 +1,196 @@
+# 助教详情:阿清(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础139.9h,附加0.0h;客户流水¥53805.04,充值归因¥0.00;头部客户(12月)Top3:陈腾鑫、葛先生、梅。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_饭团.csv b/etl_billiards/docs/table_2025-12-19/助教详情_饭团.csv
new file mode 100644
index 0000000..4a01a9e
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_饭团.csv
@@ -0,0 +1,46 @@
+助教详情:饭团(2025年10-12月)
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。评价:基础16.0h,附加0.0h;客户流水¥7955.28,充值归因¥0.00;头部客户(12月)Top3:轩哥、张先生。
+
+一、基础课业绩
+说明:评价:基础16.0h,附加0.0h;客户流水¥7955.28,充值归因¥0.00;头部客户(12月)Top3:轩哥、张先生。
+
+月份,基础课业绩,基础课业绩,基础课业绩,基础课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,16.00h,16,-28.41h,-20.53h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+二、附加课业绩
+说明:附加课=order_assistant_type=2。
+
+月份,附加课业绩,附加课业绩,附加课业绩,附加课业绩
+月份,小时数,排名,平均值差值小时数,中位数值差值小时数
+10月,0.00h,,0.00h,0.00h
+11月,0.00h,,0.00h,0.00h
+12月,0.00h,,0.00h,0.00h
+
+三、客户消费业绩
+说明:订单台费+助教+商品应付金额全额计入订单内助教。
+
+月份,客户消费业绩,客户消费业绩,客户消费业绩,客户消费业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,7955.28,16,-21324.25,-22694.55
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+四、客户充值业绩
+说明:充值命中消费窗口±30分钟且有助教则归因;全额复制。
+
+月份,客户充值业绩,客户充值业绩,客户充值业绩,客户充值业绩
+月份,合计元,排名,平均值差值元,中位数值差值元
+10月,0.00,,0.00,0.00
+11月,0.00,,0.00,0.00
+12月,0.00,,0.00,0.00
+
+五、头部客户(按12月消费业绩排序,Top100)
+说明:基础/附加课时=基础h/附加h。
+
+排名,客户名称,12月,12月,12月,11月,11月,11月,10月,10月,10月
+排名,客户名称,基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元),基础/附加课时,消费业绩(元),客户充值(元)
+1,轩哥,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,6.9h / 0.0h,5089.50,0.00
+2,张先生,0.0h / 0.0h,0.00,0.00,0.0h / 0.0h,0.00,0.00,9.1h / 0.0h,2865.78,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/助教详情_饭团.md b/etl_billiards/docs/table_2025-12-19/助教详情_饭团.md
new file mode 100644
index 0000000..e47ee2e
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/助教详情_饭团.md
@@ -0,0 +1,196 @@
+# 助教详情:饭团(2025年10-12月)
+## 思考过程
+按模板拆分5部分输出;月度排名采用dense_rank;均值/中位数在当月该指标>0助教集合上计算。
+
+## 查询说明
+本表包含5个部分:基础课业绩、附加课业绩、客户消费业绩、客户充值业绩、头部客户情况。均值/中位数差值对比集合为当月该指标>0的助教。充值/客户流水多助教与多订单命中均按全额复制计入,故汇总可能大于门店总额。
+评价:基础16.0h,附加0.0h;客户流水¥7955.28,充值归因¥0.00;头部客户(12月)Top3:轩哥、张先生。
+
+## SQL
+
+### 服务时长(助教-客户-月份)
+```sql
+with raw as (
+ select
+ asl.nickname as assistant,
+ asl.tenant_member_id as member_id,
+ case when asl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when asl.start_use_time >= '2025-11-01 00:00:00+08'::timestamptz and asl.start_use_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ asl.order_assistant_type,
+ asl.income_seconds
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ and asl.tenant_member_id is not null and asl.tenant_member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(case when order_assistant_type=1 then income_seconds else 0 end)/3600.0 as base_hours,
+ sum(case when order_assistant_type=2 then income_seconds else 0 end)/3600.0 as extra_hours
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 客户流水(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_amount as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ bo.order_start_time,
+ bo.order_end_time,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_amount a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+raw as (
+ select
+ ao.assistant,
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ join assistant_orders ao on ao.order_settle_id=o.order_settle_id
+ where o.member_id is not null and o.member_id<>0
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(order_amount) as revenue_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
+
+### 充值归因(助教-客户-月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as table_start_time,
+ max(tfl.ledger_end_time) as table_end_time
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_time as (
+ select
+ asl.order_settle_id,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id=asl.order_settle_id
+ where asl.site_id=%(site_id)s and coalesce(asl.is_delete,0)=0
+ group by asl.order_settle_id
+),
+order_windows as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.table_start_time, coalesce(at.assistant_start_time, bo.table_start_time)) as win_start,
+ greatest(bo.table_end_time, coalesce(at.assistant_end_time, bo.table_end_time)) as win_end
+ from base_orders bo
+ left join assistant_time at on at.order_settle_id=bo.order_settle_id
+ where bo.member_id is not null and bo.member_id<>0
+),
+assistant_orders as (
+ select distinct order_settle_id, nickname as assistant
+ from billiards_dwd.dwd_assistant_service_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz
+ and start_use_time < %(window_end)s::timestamptz
+),
+recharge_pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id=p.relate_id
+ where p.site_id=%(site_id)s
+ and p.relate_type=5
+ and p.pay_status=2
+ and p.pay_amount>0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+),
+matched as (
+ select
+ rp.pay_time,
+ ow.order_settle_id,
+ ow.member_id,
+ rp.pay_amount
+ from recharge_pay rp
+ join order_windows ow
+ on ow.member_id=rp.member_id
+ and rp.pay_time >= ow.win_start - interval '30 minutes'
+ and rp.pay_time <= ow.win_end + interval '30 minutes'
+),
+raw as (
+ select
+ ao.assistant,
+ m.member_id,
+ case when m.pay_time >= '2025-10-01 00:00:00+08'::timestamptz and m.pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when m.pay_time >= '2025-11-01 00:00:00+08'::timestamptz and m.pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when m.pay_time >= '2025-12-01 00:00:00+08'::timestamptz and m.pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ m.pay_amount
+ from matched m
+ join assistant_orders ao on ao.order_settle_id=m.order_settle_id
+)
+select
+ assistant,
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_amount
+from raw
+where month_key is not null
+group by assistant, member_id, month_key;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.csv b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.csv
new file mode 100644
index 0000000..d0a15d3
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.csv
@@ -0,0 +1,105 @@
+2025年10-12月 客户消费能力Top100(分表)
+与总表同口径;分表仅计算12月喜爱助教Top5,并展示10-12月各月消费/充值。
+
+排名,客户名称,电话号码,12月,12月,12月,11月,11月,10月,10月
+排名,客户名称,电话号码,喜爱助教昵称,消费(元),充值(元),消费(元),充值(元),消费(元),充值(元)
+ 1,轩哥,188****7530,七七(65.8h)、璇子(37.7h)、涛涛(10.8h)、Amy(8.8h)、小柔(8.4h),29170.33,0.00,51318.11,13000.00,72647.61,53000.00
+ 2,蔡总,159****8893,小柔(30.2h)、七七(26.7h)、瑶瑶(19.5h)、璇子(18.3h)、涛涛(15.1h),34327.09,0.00,115512.37,5000.00,0.00,0.00
+ 3,葛先生,138****8071,小燕(104.8h)、阿清(7.9h)、涛涛(5.9h)、梦梦(2.9h)、年糕(2.6h),23237.78,0.00,24991.55,0.00,0.00,0.00
+ 4,罗先生,139****6996,佳怡(73.8h)、苏苏(19.6h)、璇子(5.3h)、周周(2.6h)、球球(2.3h),17515.75,0.00,16177.44,0.00,12880.69,10000.00
+ 5,陈腾鑫,178****8218,阿清(34.9h)、小侯(12.1h)、千千(4.9h)、小柔(1.7h),10701.83,0.00,19428.27,1000.00,9945.66,8000.00
+ 6,江先生,188****4838,璇子(38.7h)、婉婉(4.7h)、小柔(3.2h)、七七(3.2h)、Amy(2.2h),10050.26,0.00,14700.83,5000.00,5721.32,6000.00
+ 7,小燕,178****1334,小燕(85.7h)、Amy(1.0h)、年糕(0.5h),17306.66,0.00,12582.23,0.00,0.00,0.00
+ 8,张先生,139****8852,小侯(14.5h)、千千(10.0h)、阿清(7.2h)、苏苏(3.9h)、乔西(3.3h),7533.67,0.00,8692.62,0.00,9878.04,0.00
+ 9,曾巧明,186****1488,,6331.51,0.00,8821.59,0.00,9677.06,0.00
+ 10,黄生,136****9719,,4181.24,0.00,6353.05,0.00,7871.94,0.00
+ 11,夏,191****2851,,0.00,0.00,4318.15,6000.00,12281.44,11000.00
+ 12,叶先生,138****9539,素素(3.1h)、年糕(2.6h),1658.40,0.00,3725.65,0.00,9107.20,6307.00
+ 13,T,180****9962,球球(10.7h)、周周(10.1h)、乔西(6.9h)、苏苏(4.5h)、小侯(3.9h),6777.66,0.00,2490.70,0.00,4382.70,3000.00
+ 14,林先生,133****1070,七七(14.0h)、璇子(9.6h)、苏苏(4.9h)、乔西(4.6h)、佳怡(4.5h),9468.05,0.00,3469.81,0.00,0.00,0.00
+ 15,曾丹烨,139****3242,,2485.41,0.00,5168.56,0.00,4702.36,3000.00
+ 16,胡先生,186****3391,佳怡(3.0h),522.45,0.00,10898.42,8000.00,0.00,0.00
+ 17,艾宇民,150****9958,,1179.56,0.00,7185.78,0.00,2397.73,0.00
+ 18,谢俊,186****5198,,969.66,0.00,4819.27,0.00,4193.93,0.00
+ 19,周周,198****8725,周周(40.8h)、球球(15.2h)、佳怡(13.2h),8905.19,0.00,0.00,0.00,0.00,0.00
+ 20,叶总,137****3287,,0.00,0.00,0.00,0.00,8163.28,5700.00
+ 21,羊,187****5094,,0.00,0.00,4534.79,16000.00,3620.75,48000.00
+ 22,游,172****6666,佳怡(3.2h)、周周(2.4h)、千千(2.2h)、QQ(1.2h),2795.90,0.00,5001.47,0.00,0.00,0.00
+ 23,桂先生,166****7275,,606.24,0.00,4788.94,0.00,2283.11,985.00
+ 24,明哥,166****0999,婉婉(26.7h)、小柔(25.7h)、年糕(4.6h)、周周(0.4h)、Amy(0.1h),5322.90,0.00,2258.14,0.00,0.00,0.00
+ 25,陈德韩,134****7864,,20.00,0.00,0.00,0.00,7282.92,5000.00
+ 26,小熊,139****0145,,0.00,0.00,5213.64,4000.00,1922.24,1000.00
+ 27,黄先生,135****3507,苏苏(9.6h)、千千(6.2h),2506.04,0.00,1926.28,0.00,2620.40,3000.00
+ 28,吕先生,155****0663,,0.00,0.00,0.00,0.00,7012.05,6000.00
+ 29,郑先生,159****4331,小敌(4.9h),1614.93,0.00,4823.14,0.00,0.00,0.00
+ 30,歌神,188****2164,,0.00,0.00,0.00,0.00,5877.65,5000.00
+ 31,罗先生,139****9222,婉婉(7.5h)、小柔(4.5h),0.00,0.00,4687.61,0.00,1143.87,3000.00
+ 32,大G,186****4598,周周(14.9h)、佳怡(9.5h)、球球(1.9h),3591.07,0.00,1783.61,0.00,0.00,0.00
+ 33,林先生,137****8785,,480.91,0.00,4486.47,0.00,0.00,0.00
+ 34,梅,136****4552,千千(10.8h)、阿清(7.5h)、小侯(3.3h),2483.11,0.00,2107.81,0.00,0.00,0.00
+ 35,李先生,134****4343,小侯(9.3h)、球球(0.0h),2395.25,0.00,2084.52,0.00,0.00,0.00
+ 36,陶,189****2151,,0.00,0.00,0.00,0.00,4096.07,6000.00
+ 37,陈先生,159****2829,,0.00,0.00,3717.58,3000.00,100.00,0.00
+ 38,候,131****0323,球球(5.3h)、阿清(4.3h)、小侯(3.4h)、涛涛(3.1h)、乔西(2.9h),3765.88,0.00,0.00,0.00,0.00,0.00
+ 39,黄先生,158****2109,球球(8.1h)、QQ(4.5h),300.15,0.00,1660.64,0.00,1608.13,3000.00
+ 40,孟紫龙,176****3741,,2888.95,0.00,603.78,0.00,0.00,0.00
+ 41,罗超,137****0990,,0.00,0.00,0.00,0.00,3398.81,3000.00
+ 42,君姐,166****4594,璇子(2.3h)、涛涛(2.2h)、年糕(2.2h),1414.23,0.00,1947.72,0.00,0.00,0.00
+ 43,吴生,136****3341,,368.03,0.00,1721.17,0.00,1164.50,0.00
+ 44,刘哥,135****0020,婉婉(0.3h),54.46,0.00,2982.34,0.00,0.00,0.00
+ 45,李先生,131****4000,,0.00,0.00,2997.53,3000.00,0.00,0.00
+ 46,阿亮,159****2628,涛涛(2.9h)、梦梦(2.7h),1133.53,0.00,1802.73,0.00,0.00,0.00
+ 47,李先生,186****8308,,0.00,0.00,2785.23,0.00,0.00,0.00
+ 48,周先生,173****7775,,0.00,0.00,0.00,0.00,2726.01,0.00
+ 49,林先生,159****0021,,0.00,0.00,2690.52,0.00,0.00,0.00
+ 50,周先生,193****6822,千千(8.6h)、素素(6.2h),2643.64,0.00,0.00,0.00,0.00,0.00
+ 51,林先生,188****0332,,0.00,0.00,2612.01,0.00,0.00,0.00
+ 52,牛先生,152****5159,,0.00,0.00,2187.48,0.00,0.00,0.00
+ 53,孟紫龙(该会员已注销),176****37411,,0.00,0.00,300.00,0.00,1831.72,0.00
+ 54,罗超杰,137****8012,,0.00,0.00,423.70,0.00,1160.35,0.00
+ 55,汪先生,139****6339,,0.00,0.00,0.00,0.00,1390.07,1000.00
+ 56,桂先生(该会员已注销),166****72751,,0.00,0.00,0.00,0.00,1370.81,0.00
+ 57,方先生,153****3185,,0.00,0.00,414.57,0.00,898.73,1000.00
+ 58,陈淑涛,132****5485,,0.00,0.00,1276.77,0.00,0.00,0.00
+ 59,清,130****3087,阿清(3.0h)、千千(3.0h)、小侯(3.0h),1128.06,0.00,0.00,0.00,0.00,0.00
+ 60,amy,137****8221,Amy(4.8h),1105.90,0.00,0.00,0.00,0.00,0.00
+ 61,曾先生,133****1235,,193.90,0.00,700.09,0.00,97.35,0.00
+ 62,昌哥,137****1229,小柔(1.8h),318.40,0.00,624.02,0.00,0.00,0.00
+ 63,李,131****9882,,0.00,0.00,320.99,0.00,606.45,0.00
+ 64,邓飛,136****9597,,0.00,0.00,925.47,1000.00,0.00,1345.00
+ 65,陈世,134****1938,,0.00,0.00,502.07,0.00,419.02,0.00
+ 66,婉婉,183****2742,,0.00,0.00,242.81,0.00,624.68,1000.00
+ 67,贺斌,150****0885,,0.00,0.00,108.29,0.00,662.27,0.00
+ 68,陈泽斌,132****6060,,100.00,0.00,500.00,0.00,100.00,0.00
+ 69,林总,138****1180,,0.00,0.00,684.44,0.00,0.00,0.00
+ 70,卢广贤,186****6220,,128.86,0.00,288.51,0.00,263.07,0.00
+ 71,王龙,186****8011,,669.58,0.00,0.00,0.00,0.00,0.00
+ 72,王先生,185****1125,,183.75,0.00,416.93,0.00,0.00,0.00
+ 73,潘先生,186****0511,年糕(2.0h),564.93,0.00,0.00,0.00,0.00,0.00
+ 74,老宋,138****4554,,0.00,0.00,465.98,0.00,75.99,0.00
+ 75,郭先生,156****5001,,0.00,0.00,281.22,0.00,237.13,0.00
+ 76,孙启明,137****6325,,0.00,0.00,200.00,0.00,300.00,0.00
+ 77,王先生,136****0168,,100.00,0.00,400.00,0.00,0.00,0.00
+ 78,黎先生,133****0983,,0.00,0.00,0.00,0.00,470.19,0.00
+ 79,常总,185****7188,阿清(1.7h)、年糕(1.7h),460.52,0.00,0.00,0.00,0.00,0.00
+ 80,张丹逸,136****6637,,100.00,0.00,0.00,0.00,339.36,0.00
+ 81,陈先生,186****8238,,0.00,0.00,416.17,0.00,0.00,0.00
+ 82,陈先生,138****3964,,100.00,0.00,0.00,0.00,300.00,0.00
+ 83,张先生,136****4528,,298.35,0.00,100.00,0.00,0.00,0.00
+ 84,小宇,187****8077,,0.00,0.00,0.00,0.00,397.50,0.00
+ 85,黄先生,191****8219,,0.00,0.00,364.33,0.00,0.00,0.00
+ 86,刘女士,177****7538,,0.00,0.00,0.00,0.00,362.58,0.00
+ 87,魏先生,137****6862,,319.39,0.00,0.00,0.00,0.00,0.00
+ 88,杜先生,188****4705,,0.00,0.00,207.47,0.00,100.00,0.00
+ 89,刘先生,137****2930,,300.00,0.00,0.00,0.00,0.00,0.00
+ 90,陈先生,133****6117,,0.00,0.00,300.00,0.00,0.00,0.00
+ 91,潘先生,176****7964,,300.00,0.00,0.00,0.00,0.00,0.00
+ 92,钟智豪,188****2803,,0.00,0.00,274.34,0.00,0.00,0.00
+ 93,都先生,138****7796,,0.00,0.00,269.64,0.00,0.00,0.00
+ 94,林志铭,135****4233,,0.00,0.00,267.96,0.00,0.00,0.00
+ 95,方先生,158****6447,,148.00,0.00,100.00,0.00,0.00,0.00
+ 96,李先生,176****5124,,0.00,0.00,0.00,0.00,244.00,0.00
+ 97,钟先生,132****3438,,0.00,0.00,0.00,0.00,239.37,0.00
+ 98,杨,130****5960,,232.00,0.00,0.00,0.00,0.00,0.00
+ 99,黄国磊,131****3045,,100.00,0.00,100.00,0.00,25.33,0.00
+ 100,周先生,159****9997,,100.00,0.00,100.00,0.00,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.md b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.md
new file mode 100644
index 0000000..8c2578b
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_分表.md
@@ -0,0 +1,199 @@
+# 2025年10-12月 客户消费能力Top100(分表)
+## 思考过程
+以台费订单为基准汇总三类明细,满足应付金额口径,并输出Top100客户的消费/充值/助教偏好。按你的要求,先生成评价为空的版本,再在脚本末尾回填评价。
+
+## 查询说明
+与总表同口径;分表仅计算12月喜爱助教Top5,并展示10-12月各月消费/充值。
+
+## SQL
+
+### Top100(按消费总额)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+select
+ o.member_id,
+ sum(o.order_amount) as consume_total,
+ count(*) as order_cnt
+from orders o
+where o.member_id is not null and o.member_id <> 0
+group by o.member_id
+order by consume_total desc
+limit 100;
+```
+
+### 按月消费汇总
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, x as (
+ select
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ where o.member_id is not null and o.member_id <> 0
+)
+select
+ member_id,
+ month_key,
+ sum(order_amount) as consume_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+```
+
+### 按月充值汇总
+```sql
+with pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id = p.relate_id
+ where p.site_id = %(site_id)s
+ and p.relate_type = 5
+ and p.pay_status = 2
+ and p.pay_amount > 0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+)
+, x as (
+ select
+ member_id,
+ case when pay_time >= '2025-10-01 00:00:00+08'::timestamptz and pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when pay_time >= '2025-11-01 00:00:00+08'::timestamptz and pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when pay_time >= '2025-12-01 00:00:00+08'::timestamptz and pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ pay_amount
+ from pay
+)
+select
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+```
+
+### 喜爱助教Top5(仅12月)
+```sql
+with x as (
+ select
+ asl.tenant_member_id as member_id,
+ asl.nickname as assistant_nickname,
+ sum(case when asl.order_assistant_type=1 then asl.income_seconds else asl.income_seconds*1.5 end) / 3600.0 as weighted_hours
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.tenant_member_id is not null and asl.tenant_member_id <> 0
+ and asl.start_use_time >= '2025-12-01 00:00:00+08'::timestamptz
+ and asl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by asl.tenant_member_id, asl.nickname
+),
+ranked as (
+ select *, row_number() over(partition by member_id order by weighted_hours desc) as rn
+ from x
+)
+select
+ member_id,
+ string_agg(assistant_nickname || '(' || to_char(round(weighted_hours::numeric, 1), 'FM999999990.0') || 'h)', '、' order by weighted_hours desc) as fav5
+from ranked
+where rn <= 5
+group by member_id;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.csv b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.csv
new file mode 100644
index 0000000..eea0105
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.csv
@@ -0,0 +1,105 @@
+2025年10-12月 客户消费能力Top100(总表)
+"消费=台费(dwd_table_fee_log.ledger_amount)+助教(dwd_assistant_service_log.ledger_amount)+商品(dwd_store_goods_sale.ledger_amount),均为应付金额(不扣优惠),以台费订单为基准串联;充值=充值支付流水(dwd_payment.relate_type=5, pay_status=2, pay_amount>0)按支付时间切月;储值卡未使用金额=当前有效储值卡余额之和(dim_member_card_account.balance, member_card_type_name='储值卡');喜爱助教=基础课时长+附加课时长*1.5(income_seconds换算小时),总表按10-12月汇总Top5。"
+
+排名,客户名称,电话号码,10月-12月,10月-12月,10月-12月,当前,评价
+排名,客户名称,电话号码,喜爱助教昵称,总消费(元),总充值(元),储值卡未使用金额(元),评价
+1,轩哥,188****7530,璇子(152.6h)、七七(129.6h)、涛涛(72.7h)、小敌(54.3h)、佳怡(50.6h),153136.05,66000.00,6050.80,订单:53单,平均单次¥2889.36;打球:279.0h,平均单次5.3h;偏好:666(54.4%)、发财(13.7%)、包厢(6.5%)、A区(5.9%);时间:到店均值16:43 中位19:21;离店均值22:31 中位次日01:03;商品:荷花双中支×56(¥3808.00)、细和天下×21(¥2625.00)、100 和成天下×13(¥1495.00)、农夫山泉苏打水×211(¥1266.00)、红牛×101(¥1010.00)、双中支中华×14(¥1008.00)(商品合计¥26812.00 占比17.5%);综合:10-12月到店消费40天/53次,到店周期中位#1,消费排名#1,在店时长#3;12月到店消费8天/9次,到店周期中位#1,消费排名#1,在店时长#7;最近到店2025-12-18;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+2,蔡总,159****8893,小柔(97.0h)、七七(72.4h)、璇子(68.2h)、涛涛(43.5h)、瑶瑶(42.8h),149839.46,5000.00,2016.18,订单:23单,平均单次¥6514.76;打球:180.4h,平均单次7.8h;偏好:发财(79.2%)、666(6.5%)、A区(4.3%)、补时长(2.8%);时间:到店均值18:05 中位20:12;离店均值次日02:58 中位次日04:48;商品:钻石荷花×100(¥4685.00)、细和天下×30(¥3750.00)、粗和天下×24(¥3000.00)、100 和成天下×20(¥2300.00)、双中支中华×31(¥2232.00)、荷花双中支×29(¥2008.00)(商品合计¥37968.00 占比25.3%);综合:10-12月到店消费22天/23次,到店周期中位#2,消费排名#2,在店时长#8;12月到店消费8天/8次,到店周期中位#1,消费排名#2,在店时长#10;最近到店2025-12-15;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:商品贡献高,可做常购商品补货提醒与组合促销
+3,葛先生,138****8071,小燕(158.3h)、阿清(27.6h)、千千(14.4h)、周周(11.0h)、年糕(9.4h),48229.33,0.00,9011.19,订单:42单,平均单次¥1148.32;打球:180.6h,平均单次4.3h;偏好:TV台(43.8%)、A区(21.2%)、包厢(20.6%)、S区/斯诺克(6.7%);时间:到店均值14:01 中位19:40;离店均值18:19 中位21:54;商品:百威235毫升×72(¥1080.00)、卡士×33(¥726.00)、风花雪月×36(¥576.00)、细荷花×7(¥370.00)、蜂蜜水×36(¥360.00)、东方树叶×39(¥312.00)(商品合计¥5432.00 占比11.3%);综合:10-12月到店消费25天/42次,到店周期中位#1,消费排名#3,在店时长#7;12月到店消费11天/24次,到店周期中位#1,消费排名#3,在店时长#2;最近到店2025-12-19;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+4,罗先生,139****6996,佳怡(205.2h)、苏苏(19.6h)、璇子(13.2h)、周周(11.6h)、涛涛(10.5h),46573.88,10000.00,585.35,订单:86单,平均单次¥541.56;打球:212.7h,平均单次2.5h;偏好:TV台(39.2%)、C区(31.8%)、M7(7.8%)、麻将(5.8%);时间:到店均值15:24 中位18:18;离店均值18:05 中位20:27;商品:百威235毫升×94(¥1410.00)、东方树叶×39(¥312.00)、细荷花×6(¥300.00)、荷花双中支×4(¥276.00)、中支芙蓉王×6(¥228.00)、哇哈哈矿泉水×38(¥190.00)(商品合计¥4390.00 占比9.4%);综合:10-12月到店消费59天/86次,到店周期中位#1,消费排名#4,在店时长#5;12月到店消费17天/25次,到店周期中位#1,消费排名#4,在店时长#5;最近到店2025-12-18;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:商品贡献高,可做常购商品补货提醒与组合促销
+5,陈腾鑫,178****8218,阿清(79.2h)、佳怡(57.7h)、球球(34.2h)、小侯(19.1h)、千千(7.7h),40075.76,9000.00,0.00,订单:93单,平均单次¥430.92;打球:207.0h,平均单次2.2h;偏好:麻将(25.0%)、C区(18.7%)、TV台(13.6%)、包厢(11.4%);时间:到店均值17:33 中位20:09;离店均值19:45 中位22:28;商品:百威235毫升×27(¥405.00)、东方树叶×50(¥400.00)、哇哈哈矿泉水×41(¥205.00)、荷花双中支×2(¥144.00)、地道肠×27(¥135.00)、哈啤×12(¥120.00)(商品合计¥2468.00 占比6.2%);综合:10-12月到店消费49天/93次,到店周期中位#1,消费排名#5,在店时长#6;12月到店消费11天/20次,到店周期中位#1,消费排名#5,在店时长#8;最近到店2025-12-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+6,江先生,188****4838,璇子(110.5h)、婉婉(16.8h)、小柔(12.0h)、Amy(6.7h)、周周(4.3h),30472.41,11000.00,0.00,订单:24单,平均单次¥1269.68;打球:65.6h,平均单次2.7h;偏好:包厢(44.5%)、888(15.3%)、M8(12.8%)、B区(10.3%);时间:到店均值16:05 中位19:47;离店均值18:53 中位21:24;商品:百威235毫升×480(¥7200.00)、风花雪月×28(¥448.00)、钻石荷花×7(¥330.00)、东方树叶×11(¥88.00)、双中支中华×1(¥72.00)、荷花双中支×1(¥68.00)(商品合计¥8943.00 占比29.3%);综合:10-12月到店消费21天/24次,到店周期中位#3,消费排名#6,在店时长#14;12月到店消费5天/6次,到店周期中位#3,消费排名#6,在店时长#18;最近到店2025-12-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+7,小燕,178****1334,小燕(140.1h)、阿清(2.0h)、球球(1.4h)、Amy(1.0h)、年糕(0.5h),29888.89,0.00,1802.64,订单:62单,平均单次¥482.08;打球:148.0h,平均单次2.4h;偏好:A区(55.2%)、麻将(20.7%)、S区/斯诺克(14.7%)、补时长(4.3%);时间:到店均值15:22 中位19:05;离店均值17:50 中位21:43;商品:东方树叶×28(¥224.00)、双中支中华×2(¥144.00)、钻石荷花×2(¥90.00)、荷花双中支×1(¥68.00)、蜂蜜水×6(¥60.00)、百威235毫升×3(¥45.00)(商品合计¥863.00 占比2.9%);综合:10-12月到店消费27天/62次,到店周期中位#1,消费排名#7,在店时长#10;12月到店消费15天/30次,到店周期中位#1,消费排名#7,在店时长#3;最近到店2025-12-18;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+8,张先生,139****8852,七七(25.1h)、小侯(20.2h)、千千(14.4h)、周周(10.4h)、璇子(10.3h),26104.33,0.00,1942.41,订单:46单,平均单次¥567.49;打球:105.7h,平均单次2.3h;偏好:C区(76.3%)、666(8.8%)、麻将(5.7%)、补时长(4.8%);时间:到店均值18:43 中位18:47;离店均值21:25 中位21:12;商品:东方树叶×28(¥224.00)、哇哈哈矿泉水×41(¥205.00)、钻石荷花×3(¥135.00)、细和天下×1(¥125.00)、双中支中华×1(¥72.00)、农夫山泉苏打水×11(¥66.00)(商品合计¥1205.00 占比4.6%);综合:10-12月到店消费40天/46次,到店周期中位#1,消费排名#8,在店时长#13;12月到店消费13天/13次,到店周期中位#1,消费排名#8,在店时长#13;最近到店2025-12-18;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+9,曾巧明,186****1488,,24830.16,0.00,0.00,订单:59单,平均单次¥420.85;打球:404.3h,平均单次6.9h;偏好:B区(66.4%)、C区(32.8%)、A区(0.8%);时间:到店均值17:01 中位16:13;离店均值23:52 中位次日00:12;商品:跨越贵烟×1(¥30.00)、地道肠×4(¥20.00)、东方树叶×2(¥16.00)、可乐×2(¥10.00)、哇哈哈矿泉水×2(¥10.00)(商品合计¥86.00 占比0.3%);综合:10-12月到店消费54天/59次,到店周期中位#1,消费排名#9,在店时长#1;12月到店消费15天/16次,到店周期中位#1,消费排名#9,在店时长#1;最近到店2025-12-18;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+10,黄生,136****9719,,18406.23,0.00,0.00,订单:36单,平均单次¥511.28;打球:298.2h,平均单次8.3h;偏好:B区(64.4%)、C区(35.6%);时间:到店均值13:13 中位12:53;离店均值21:30 中位22:04;商品:地道肠×8(¥40.00)、可乐×2(¥10.00)(商品合计¥50.00 占比0.3%);综合:10-12月到店消费36天/36次,到店周期中位#1,消费排名#10,在店时长#2;12月到店消费7天/7次,到店周期中位#3,消费排名#10,在店时长#4;最近到店2025-12-18;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+11,夏,191****2851,婉婉(29.7h)、柚子(10.7h)、球球(10.6h)、佳怡(7.8h)、璇子(7.6h),16599.59,17000.00,0.00,订单:10单,平均单次¥1659.96;打球:40.5h,平均单次4.1h;偏好:888(72.1%)、TV台(22.1%)、包厢(5.8%)、补时长(0.0%);时间:到店均值18:28 中位20:36;离店均值22:43 中位次日01:10;商品:百威235毫升×247(¥3705.00)、细荷花×5(¥250.00)、荷花双中支×3(¥204.00)、清洁费150×1(¥150.00)、三只松鼠开心果×4(¥120.00)、鸡翅三个一份×6(¥108.00)(商品合计¥5162.90 占比31.1%);综合:10-12月到店消费9天/10次,到店周期中位#5,消费排名#11,在店时长#19;12月到店消费0天/0次,到店周期中位—,消费排名#11,在店时长—;最近到店2025-11-06;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+12,叶先生,138****9539,素素(29.7h)、年糕(9.7h)、Amy(7.4h)、球球(6.7h)、婉婉(3.7h),14491.25,6307.00,0.00,订单:8单,平均单次¥1811.41;打球:27.2h,平均单次3.4h;偏好:B区(30.9%)、888(24.0%)、C区(17.8%)、包厢(16.3%);时间:到店均值18:38 中位20:59;离店均值次日00:04 中位次日02:12;商品:蓝妹×96(¥1728.00)、钻石荷花×9(¥405.00)、50 和成天下×6(¥390.00)、鸡翅三个一份×14(¥252.00)、100 和成天下×2(¥230.00)、透明袋无穷鸡翅×10(¥200.00)(商品合计¥4880.00 占比33.7%);综合:10-12月到店消费8天/8次,到店周期中位#2,消费排名#12,在店时长#27;12月到店消费2天/2次,到店周期中位#1,消费排名#12,在店时长#37;最近到店2025-12-06;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+13,T,180****9962,佳怡(15.0h)、周周(14.7h)、乔西(11.2h)、球球(10.7h)、欣怡(10.3h),13651.06,3000.00,849.68,订单:16单,平均单次¥853.19;打球:55.6h,平均单次3.5h;偏好:麻将(50.8%)、M8(17.0%)、包厢(16.0%)、A区(9.2%);时间:到店均值18:05 中位19:34;离店均值21:23 中位22:01;商品:荷花双中支×4(¥288.00)、钻石荷花×4(¥190.00)、软荷花×3(¥174.00)、哇哈哈矿泉水×26(¥130.00)、红牛×10(¥100.00)、跨越贵烟×3(¥86.00)(商品合计¥1689.00 占比12.4%);综合:10-12月到店消费12天/16次,到店周期中位#1,消费排名#13,在店时长#16;12月到店消费5天/8次,到店周期中位#1,消费排名#13,在店时长#14;最近到店2025-12-17;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+14,林先生,133****1070,七七(19.4h)、佳怡(14.9h)、璇子(9.6h)、乔西(9.6h)、苏苏(4.9h),12937.86,0.00,158.79,订单:14单,平均单次¥924.13;打球:44.4h,平均单次3.2h;偏好:麻将(33.6%)、M8(31.5%)、M7(21.5%)、补时长(11.4%);时间:到店均值12:18 中位17:34;离店均值15:50 中位次日01:15;商品:荷花双中支×5(¥360.00)、细荷花×5(¥260.00)、细和天下×2(¥250.00)、钻石荷花×5(¥250.00)、双中支中华×3(¥216.00)、粗和天下×1(¥125.00)(商品合计¥2246.00 占比17.4%);综合:10-12月到店消费13天/14次,到店周期中位#1,消费排名#14,在店时长#17;12月到店消费10天/11次,到店周期中位#1,消费排名#14,在店时长#12;最近到店2025-12-13;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;商品贡献高,可做常购商品补货提醒与组合促销
+15,曾丹烨,139****3242,,12356.33,3000.00,6639.14,订单:54单,平均单次¥228.82;打球:256.7h,平均单次4.8h;偏好:麻将(100.0%);时间:到店均值16:05 中位17:32;离店均值20:29 中位22:06;商品:合味道泡面×1(¥12.00)、地道肠×2(¥10.00)、东鹏特饮×1(¥7.00)、喜之郎果冻×1(¥5.00)(商品合计¥34.00 占比0.3%);综合:10-12月到店消费44天/54次,到店周期中位#1,消费排名#15,在店时长#4;12月到店消费9天/11次,到店周期中位#2,消费排名#15,在店时长#6;最近到店2025-12-16;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+16,胡先生,186****3391,佳怡(29.4h)、七七(4.2h)、球球(3.9h)、婉婉(3.9h)、涛涛(2.7h),11420.87,8000.00,0.00,订单:9单,平均单次¥1268.99;打球:39.8h,平均单次4.4h;偏好:包厢(44.2%)、A区(23.1%)、888(11.9%)、麻将(10.7%);时间:到店均值13:36 中位17:09;离店均值17:14 中位20:36;商品:百威235毫升×70(¥1050.00)、钻石荷花×5(¥225.00)、鸡翅三个一份×4(¥72.00)、蜂蜜水×7(¥70.00)、50 和成天下×1(¥65.00)、软荷花×1(¥58.00)(商品合计¥1900.00 占比16.6%);综合:10-12月到店消费5天/9次,到店周期中位#6,消费排名#16,在店时长#20;12月到店消费1天/1次,到店周期中位—,消费排名#16,在店时长#41;最近到店2025-12-01;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化
+17,艾宇民,150****9958,泡芙(22.0h)、小侯(7.6h),10763.07,0.00,0.00,订单:44单,平均单次¥244.62;打球:112.4h,平均单次2.6h;偏好:B区(82.1%)、C区(12.7%)、包厢(5.2%);时间:到店均值16:20 中位16:06;离店均值18:50 中位18:03;商品:百威235毫升×30(¥450.00)、地道肠×13(¥65.00)、细荷花×1(¥50.00)、中支芙蓉王×1(¥38.00)、乖媳妇山椒泡爪×1(¥25.00)、哇哈哈矿泉水×5(¥25.00)(商品合计¥808.00 占比7.5%);综合:10-12月到店消费41天/44次,到店周期中位#1,消费排名#17,在店时长#12;12月到店消费8天/10次,到店周期中位#2,消费排名#17,在店时长#16;最近到店2025-12-17;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+18,谢俊,186****5198,年糕(4.5h)、素素(2.4h),9982.86,0.00,0.00,订单:46单,平均单次¥217.02;打球:159.5h,平均单次3.5h;偏好:B区(100.0%);时间:到店均值19:31 中位20:12;离店均值22:59 中位23:48;商品:钻石荷花×1(¥45.00)(商品合计¥45.00 占比0.5%);综合:10-12月到店消费43天/46次,到店周期中位#1,消费排名#18,在店时长#9;12月到店消费4天/6次,到店周期中位#5,消费排名#18,在店时长#19;最近到店2025-12-17;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+19,周周,198****8725,周周(70.8h)、球球(15.2h)、佳怡(13.2h),8905.19,0.00,0.00,订单:10单,平均单次¥890.52;打球:35.9h,平均单次3.6h;偏好:麻将(59.3%)、M7(19.6%)、补时长(19.6%)、A区(1.5%);时间:到店均值11:40 中位14:30;离店均值17:04 中位次日00:34;商品:哇哈哈AD钙奶×13(¥104.00)、跨越贵烟×3(¥90.00)、细荷花×1(¥55.00)、红利群×2(¥52.00)、钻石荷花×1(¥50.00)、哇哈哈矿泉水×7(¥35.00)(商品合计¥685.00 占比7.7%);综合:10-12月到店消费8天/10次,到店周期中位#1,消费排名#19,在店时长#22;12月到店消费8天/10次,到店周期中位#1,消费排名#19,在店时长#11;最近到店2025-12-17;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+20,叶总,137****3287,璇子(22.0h)、小柔(3.8h)、七七(3.0h),8163.28,5700.00,0.00,订单:5单,平均单次¥1632.66;打球:23.4h,平均单次4.7h;偏好:包厢(53.5%)、888(25.5%)、麻将(12.9%)、B区(8.2%);时间:到店均值21:36 中位21:10;离店均值次日02:18 中位次日02:08;商品:百威235毫升×132(¥1980.00)、荷花双中支×3(¥204.00)、软荷花×1(¥58.00)、跨越贵烟×2(¥56.00)、细荷花×1(¥50.00)、钻石荷花×1(¥45.00)(商品合计¥2487.00 占比30.5%);综合:10-12月到店消费5天/5次,到店周期中位#2,消费排名#20,在店时长#31;12月到店消费0天/0次,到店周期中位—,消费排名#20,在店时长—;最近到店2025-10-27;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化;商品贡献高,可做常购商品补货提醒与组合促销
+21,羊,187****5094,球球(5.3h)、璇子(5.0h)、素素(4.3h)、婉婉(4.3h)、Amy(4.1h),8155.54,64000.00,0.00,订单:13单,平均单次¥627.35;打球:35.7h,平均单次2.7h;偏好:麻将(64.8%)、TV台(14.7%)、B区(10.3%)、888(9.7%);时间:到店均值18:13 中位19:52;离店均值21:16 中位22:36;商品:蓝妹×54(¥972.00)、钻石荷花×4(¥180.00)、中支芙蓉王×2(¥76.00)、无穷烤小腿×3(¥60.00)、跨越贵烟×2(¥56.00)、鸡翅三个一份×3(¥54.00)(商品合计¥2072.00 占比25.4%);综合:10-12月到店消费10天/13次,到店周期中位#1,消费排名#21,在店时长#23;12月到店消费0天/0次,到店周期中位—,消费排名#21,在店时长—;最近到店2025-11-23;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;商品贡献高,可做常购商品补货提醒与组合促销
+22,游,172****6666,佳怡(13.5h)、小敌(3.6h)、璇子(3.1h)、周周(2.4h)、千千(2.2h),7797.37,0.00,0.00,订单:13单,平均单次¥599.80;打球:24.1h,平均单次1.9h;偏好:包厢(52.1%)、666(31.7%)、补时长(8.5%)、S区/斯诺克(7.7%);时间:到店均值19:13 中位18:51;离店均值21:14 中位20:36;商品:双中支中华×3(¥216.00)、红牛×17(¥170.00)、跨越贵烟×5(¥140.00)、荷花双中支×2(¥136.00)、50枸杞槟榔×2(¥130.00)、100 和成天下×1(¥115.00)(商品合计¥1406.00 占比18.0%);综合:10-12月到店消费9天/13次,到店周期中位#2,消费排名#22,在店时长#29;12月到店消费6天/9次,到店周期中位#1,消费排名#22,在店时长#27;最近到店2025-12-13;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+23,桂先生,166****7275,球球(2.6h),7678.29,985.00,0.00,订单:21单,平均单次¥365.63;打球:117.4h,平均单次5.6h;偏好:B区(79.3%)、C区(20.7%);时间:到店均值18:37 中位19:01;离店均值次日00:12 中位次日00:13;商品:地道肠×17(¥85.00)、哇哈哈矿泉水×15(¥75.00)、可乐×13(¥65.00)、红牛×4(¥40.00)、蜂蜜水×3(¥30.00)、东方树叶×3(¥24.00)(商品合计¥373.00 占比4.9%);综合:10-12月到店消费21天/21次,到店周期中位#2,消费排名#23,在店时长#11;12月到店消费2天/2次,到店周期中位#9,消费排名#23,在店时长#26;最近到店2025-12-16;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益
+24,明哥,166****0999,小柔(31.6h)、婉婉(26.7h)、涛涛(5.4h)、年糕(4.6h)、周周(0.4h),7581.04,0.00,954.64,订单:4单,平均单次¥1895.26;打球:21.1h,平均单次5.3h;偏好:包厢(43.0%)、A区(26.0%)、补时长(23.8%)、C区(5.2%);时间:到店均值10:22 中位10:15;离店均值13:40 中位13:49;商品:百威235毫升×78(¥1170.00)、硬中华×2(¥100.00)、地道肠×9(¥45.00)、东方树叶×4(¥32.00)、鱼蛋×6(¥30.00)、蜂蜜水×2(¥20.00)(商品合计¥1447.00 占比19.1%);综合:10-12月到店消费4天/4次,到店周期中位#5,消费排名#24,在店时长#35;12月到店消费3天/3次,到店周期中位#5,消费排名#24,在店时长#20;最近到店2025-12-10;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+25,陈德韩,134****7864,乔西(9.1h)、素素(5.5h)、奈千(4.4h)、周周(4.3h)、小敌(4.0h),7302.92,5000.00,20.11,订单:4单,平均单次¥1825.73;打球:19.6h,平均单次4.9h;偏好:包厢(66.6%)、888(21.3%)、麻将(12.1%)、补时长(0.0%);时间:到店均值18:53 中位18:48;离店均值21:23 中位21:56;商品:百威235毫升×85(¥1275.00)、卡士×9(¥198.00)、无穷爱辣烤鸡爪×3(¥60.00)、鸡翅三个一份×2(¥36.00)、鱼蛋×6(¥30.00)、鱼豆腐×2(¥30.00)(商品合计¥1898.00 占比26.0%);综合:10-12月到店消费4天/4次,到店周期中位#15,消费排名#25,在店时长#38;12月到店消费1天/1次,到店周期中位—,消费排名#25,在店时长—;最近到店2025-12-01;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+26,小熊,139****0145,佳怡(13.2h)、周周(10.7h)、欣怡(7.9h)、球球(4.4h)、七七(1.3h),7135.88,5000.00,0.00,订单:9单,平均单次¥792.88;打球:32.7h,平均单次3.6h;偏好:麻将(82.3%)、包厢(9.2%)、TV台(8.5%)、补时长(0.0%);时间:到店均值14:59 中位18:25;离店均值19:25 中位23:36;商品:软荷花×3(¥174.00)、100 和成天下×1(¥115.00)、中支芙蓉王×3(¥114.00)、钻石荷花×2(¥90.00)、炫赫门小南京×3(¥78.00)、荷花双中支×1(¥68.00)(商品合计¥1223.00 占比17.1%);综合:10-12月到店消费6天/9次,到店周期中位#2,消费排名#26,在店时长#25;12月到店消费0天/0次,到店周期中位—,消费排名#26,在店时长—;最近到店2025-11-05;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化
+27,黄先生,135****3507,苏苏(30.8h)、千千(13.1h)、乔西(1.6h)、阿清(0.7h),7052.72,3000.00,1639.43,订单:22单,平均单次¥320.58;打球:39.4h,平均单次1.8h;偏好:B区(80.5%)、A区(17.0%)、C区(2.2%)、补时长(0.4%);时间:到店均值18:32 中位19:27;离店均值20:30 中位21:28;商品:东方树叶×6(¥48.00)、钻石荷花×1(¥45.00)、哇哈哈AD钙奶×4(¥32.00)、东鹏特饮×3(¥21.00)、无穷烤小腿×1(¥20.00)、综合蔬果干×1(¥15.00)(商品合计¥225.00 占比3.2%);综合:10-12月到店消费20天/22次,到店周期中位#3,消费排名#27,在店时长#21;12月到店消费7天/7次,到店周期中位#2,消费排名#27,在店时长#22;最近到店2025-12-16;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+28,吕先生,155****0663,小柔(7.5h)、周周(3.7h)、素素(2.8h)、婉婉(2.8h)、苏苏(2.8h),7012.05,6000.00,0.00,订单:4单,平均单次¥1753.01;打球:17.0h,平均单次4.2h;偏好:666(66.5%)、888(18.2%)、麻将(15.3%);时间:到店均值14:20 中位18:05;离店均值18:34 中位21:28;商品:蓝妹×35(¥630.00)、软中华×3(¥210.00)、红牛×17(¥170.00)、软荷花×2(¥116.00)、鸡翅三个一份×4(¥72.00)、地道肠×10(¥50.00)(商品合计¥1819.00 占比25.9%);综合:10-12月到店消费4天/4次,到店周期中位#1,消费排名#28,在店时长#41;12月到店消费0天/0次,到店周期中位—,消费排名#28,在店时长—;最近到店2025-10-20;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益
+29,郑先生,159****4331,小敌(32.1h),6438.07,0.00,0.00,订单:16单,平均单次¥402.38;打球:42.2h,平均单次2.6h;偏好:C区(63.7%)、补时长(14.4%)、B区(12.9%)、A区(9.0%);时间:到店均值15:29 中位20:24;离店均值19:22 中位次日00:03;商品:农夫山泉苏打水×8(¥48.00)、蜂蜜水×4(¥40.00)、地道肠×7(¥35.00)、一次性手套×5(¥10.00)、东方树叶×1(¥8.00)、哇哈哈矿泉水×1(¥5.00)(商品合计¥156.00 占比2.4%);综合:10-12月到店消费13天/16次,到店周期中位#1,消费排名#29,在店时长#18;12月到店消费5天/7次,到店周期中位#1,消费排名#29,在店时长#25;最近到店2025-12-12;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+30,歌神,188****2164,婉婉(6.7h)、希希(4.0h)、素素(3.9h)、小柔(3.8h)、年糕(2.6h),5877.65,5000.00,0.00,订单:4单,平均单次¥1469.41;打球:12.8h,平均单次3.2h;偏好:888(43.0%)、包厢(41.0%)、麻将(16.0%);时间:到店均值22:20 中位22:39;离店均值次日01:34 中位次日01:19;商品:百威235毫升×90(¥1350.00)、鸡翅三个一份×5(¥90.00)、焦糖瓜子×3(¥45.00)、鱼蛋×9(¥45.00)、三只松鼠开心果×1(¥30.00)、地道肠×6(¥30.00)(商品合计¥1687.00 占比28.7%);综合:10-12月到店消费4天/4次,到店周期中位#4,消费排名#30,在店时长#46;12月到店消费0天/0次,到店周期中位—,消费排名#30,在店时长—;最近到店2025-10-24;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益;重点维护包厢/团建需求,提前锁档与套餐化
+31,罗先生,139****9222,婉婉(18.8h)、年糕(7.7h)、小柔(4.5h)、素素(4.3h)、姜姜(1.5h),5831.48,3000.00,310.31,订单:5单,平均单次¥1166.30;打球:20.0h,平均单次4.0h;偏好:包厢(72.1%)、888(17.8%)、补时长(10.2%);时间:到店均值16:46 中位21:04;离店均值次日01:10 中位次日00:07;商品:科罗娜啤酒275ml×26(¥468.00)、蓝妹×18(¥324.00)、鸡翅三个一份×2(¥36.00)、三只松鼠开心果×1(¥30.00)、地道肠×5(¥25.00)、焦糖瓜子×1(¥15.00)(商品合计¥924.00 占比15.8%);综合:10-12月到店消费5天/5次,到店周期中位#14,消费排名#31,在店时长#37;12月到店消费0天/0次,到店周期中位—,消费排名#31,在店时长—;最近到店2025-11-27;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+32,大G,186****4598,周周(17.7h)、佳怡(9.5h)、球球(1.9h),5374.68,0.00,0.00,订单:5单,平均单次¥1074.94;打球:21.6h,平均单次4.3h;偏好:麻将(47.3%)、M7(33.2%)、A区(19.4%)、补时长(0.1%);时间:到店均值17:16 中位20:28;离店均值21:48 中位次日00:04;商品:荷花双中支×2(¥144.00)、哇哈哈AD钙奶×9(¥72.00)、无穷烤小腿×3(¥60.00)、芙蓉王×2(¥56.00)、红利群×2(¥52.00)、蜂蜜水×4(¥40.00)(商品合计¥748.00 占比13.9%);综合:10-12月到店消费5天/5次,到店周期中位#1,消费排名#32,在店时长#34;12月到店消费4天/4次,到店周期中位#1,消费排名#32,在店时长#24;最近到店2025-12-07;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+33,林先生,137****8785,小侯(9.7h)、梦梦(4.3h)、千千(2.7h)、瑶瑶(1.9h)、周周(0.7h),4967.38,0.00,0.00,订单:7单,平均单次¥709.63;打球:18.7h,平均单次2.7h;偏好:C区(76.5%)、包厢(23.4%)、补时长(0.0%);时间:到店均值17:58 中位19:48;离店均值20:49 中位23:39;商品:百威235毫升×30(¥450.00)、50枸杞槟榔×1(¥65.00)、东方树叶×5(¥40.00)、蜂蜜水×4(¥40.00)、哇哈哈矿泉水×7(¥35.00)、酒鬼花生×4(¥32.00)(商品合计¥887.00 占比17.9%);综合:10-12月到店消费6天/7次,到店周期中位#3,消费排名#33,在店时长#40;12月到店消费2天/2次,到店周期中位#4,消费排名#33,在店时长#34;最近到店2025-12-06;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+34,梅,136****4552,千千(16.6h)、阿清(10.8h)、小侯(4.7h)、小燕(3.8h),4590.92,0.00,2050.00,订单:8单,平均单次¥573.86;打球:20.4h,平均单次2.5h;偏好:麻将(77.0%)、C区(12.1%)、补时长(10.8%);时间:到店均值14:47 中位20:54;离店均值20:02 中位23:31;商品:硬中华×1(¥50.00)、轻上椰子水×2(¥24.00)、哇哈哈矿泉水×2(¥10.00)(商品合计¥84.00 占比1.8%);综合:10-12月到店消费7天/8次,到店周期中位#5,消费排名#34,在店时长#36;12月到店消费5天/5次,到店周期中位#5,消费排名#34,在店时长#23;最近到店2025-12-19;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+35,李先生,134****4343,小侯(9.3h)、柚子(7.8h)、球球(0.0h),4479.77,0.00,2433.01,订单:8单,平均单次¥559.97;打球:32.1h,平均单次4.0h;偏好:C区(73.4%)、包厢(26.6%);时间:到店均值19:34 中位20:19;离店均值23:35 中位23:13;商品:热水可续杯×13(¥39.00)、农夫山泉苏打水×5(¥30.00)、水果脆×1(¥30.00)、跨越贵烟×1(¥30.00)、哇哈哈矿泉水×4(¥20.00)、水溶C×1(¥8.00)(商品合计¥185.00 占比4.1%);综合:10-12月到店消费8天/8次,到店周期中位#3,消费排名#35,在店时长#26;12月到店消费5天/5次,到店周期中位#3,消费排名#35,在店时长#17;最近到店2025-12-18;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+36,陶,189****2151,欣怡(4.9h)、球球(4.7h)、周周(4.4h)、七七(4.2h)、佳怡(4.1h),4096.07,6000.00,8.82,订单:7单,平均单次¥585.15;打球:21.7h,平均单次3.1h;偏好:麻将(61.0%)、A区(13.3%)、包厢(9.7%)、C区(8.1%);时间:到店均值20:49 中位21:49;离店均值23:55 中位次日01:19;商品:荷花双中支×1(¥68.00)、红牛×5(¥50.00)、轻上椰子水×4(¥48.00)、哇哈哈矿泉水×8(¥40.00)、软玉溪×1(¥28.00)、炫赫门小南京×1(¥26.00)(商品合计¥399.00 占比9.7%);综合:10-12月到店消费6天/7次,到店周期中位#2,消费排名#36,在店时长#33;12月到店消费0天/0次,到店周期中位—,消费排名#36,在店时长—;最近到店2025-10-26;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+37,陈先生,159****2829,佳怡(7.6h)、奈千(5.1h)、柚子(4.4h)、乔西(4.2h)、Amy(4.2h),3817.58,3000.00,0.55,订单:3单,平均单次¥1272.53;打球:7.6h,平均单次2.5h;偏好:麻将(54.5%)、TV台(45.4%)、补时长(0.1%)、A区(0.0%);时间:到店均值13:21 中位19:06;离店均值18:07 中位次日00:40;商品:百威235毫升×10(¥150.00)、钻石荷花×1(¥45.00)、跨越贵烟×1(¥28.00)、无穷爱辣烤鸡爪×1(¥20.00)、白桦树汁×1(¥12.00)、椰汁×1(¥8.00)(商品合计¥277.00 占比7.3%);综合:10-12月到店消费3天/3次,到店周期中位#19,消费排名#37,在店时长#57;12月到店消费0天/0次,到店周期中位—,消费排名#37,在店时长—;最近到店2025-11-07;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+38,候,131****0323,球球(5.3h)、阿清(4.3h)、小侯(3.4h)、涛涛(3.1h)、乔西(2.9h),3765.88,0.00,0.00,订单:8单,平均单次¥470.74;打球:22.0h,平均单次2.7h;偏好:TV台(66.3%)、A区(28.3%)、C区(5.4%);时间:到店均值20:08 中位19:43;离店均值22:53 中位22:54;商品:冰红茶×8(¥48.00)、地道肠×4(¥20.00)、鱼蛋×4(¥20.00)、可乐×2(¥10.00)、哇米诺豆奶×1(¥10.00)、红牛×1(¥10.00)(商品合计¥161.00 占比4.3%);综合:10-12月到店消费5天/8次,到店周期中位#1,消费排名#38,在店时长#32;12月到店消费5天/8次,到店周期中位#1,消费排名#38,在店时长#15;最近到店2025-12-17;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+39,黄先生,158****2109,球球(64.0h)、QQ(6.9h),3568.92,3000.00,420.01,订单:10单,平均单次¥356.89;打球:23.4h,平均单次2.3h;偏好:A区(60.1%)、包厢(27.0%)、补时长(12.9%);时间:到店均值04:58 中位01:43;离店均值06:06 中位03:20;商品:蓝妹×4(¥72.00)、跨越贵烟×1(¥28.00)、火腿肠×2(¥10.00)、东方树叶×1(¥8.00)、卫龙魔芋爽×1(¥8.00)、农夫山泉苏打水×1(¥6.00)(商品合计¥142.00 占比4.0%);综合:10-12月到店消费8天/10次,到店周期中位#4,消费排名#39,在店时长#30;12月到店消费3天/4次,到店周期中位#8,消费排名#39,在店时长#45;最近到店2025-12-17;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+40,孟紫龙,176****3741,,3492.73,0.00,0.00,订单:13单,平均单次¥268.67;打球:57.6h,平均单次4.4h;偏好:B区(100.0%);时间:到店均值18:44 中位18:50;离店均值23:10 中位23:35;商品:哇哈哈矿泉水×9(¥45.00)、东方树叶×5(¥40.00)、地道肠×7(¥35.00)、可乐×2(¥10.00)、维他柠檬茶×1(¥8.00)、脉动×1(¥8.00)(商品合计¥153.00 占比4.4%);综合:10-12月到店消费12天/13次,到店周期中位#1,消费排名#40,在店时长#15;12月到店消费10天/11次,到店周期中位#1,消费排名#40,在店时长#9;最近到店2025-12-18;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+41,罗超,137****0990,球球(2.9h)、璇子(2.7h)、苏苏(2.6h)、奈千(2.5h),3398.81,3000.00,101.19,订单:2单,平均单次¥1699.40;打球:7.3h,平均单次3.7h;偏好:888(78.8%)、麻将(21.2%);时间:到店均值20:57 中位20:57;离店均值次日00:37 中位次日00:37;商品:科罗娜啤酒275ml×49(¥882.00)、荷花双中支×1(¥68.00)、百威235毫升×3(¥45.00)、掼蛋扑克×4(¥32.00)、跨越贵烟×1(¥28.00)、东方树叶×3(¥24.00)(商品合计¥1115.00 占比32.8%);综合:10-12月到店消费2天/2次,到店周期中位#16,消费排名#41,在店时长#59;12月到店消费0天/0次,到店周期中位—,消费排名#41,在店时长—;最近到店2025-10-24;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+42,君姐,166****4594,年糕(8.2h)、婉婉(4.3h)、璇子(2.3h)、涛涛(2.2h),3361.95,0.00,272.15,订单:3单,平均单次¥1120.65;打球:12.5h,平均单次4.2h;偏好:666(30.5%)、M8(25.3%)、M7(17.7%)、包厢(13.9%);时间:到店均值15:38 中位16:21;离店均值20:33 中位21:15;商品:哇哈哈矿泉水×20(¥100.00)、卡士×2(¥44.00)、东方树叶×5(¥40.00)、麻将房茶位费×1(¥40.00)、小果盘×1(¥37.90)、软玉溪×1(¥28.00)(商品合计¥319.90 占比9.5%);综合:10-12月到店消费3天/3次,到店周期中位#5,消费排名#42,在店时长#47;12月到店消费1天/1次,到店周期中位—,消费排名#42,在店时长#31;最近到店2025-12-02;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+43,吴生,136****3341,小柔(2.8h)、涛涛(2.2h),3253.70,0.00,3680.65,订单:15单,平均单次¥216.91;打球:34.3h,平均单次2.3h;偏好:C区(86.1%)、B区(7.0%)、包厢(6.7%)、补时长(0.1%);时间:到店均值19:01 中位18:43;离店均值21:14 中位21:25;商品:哇哈哈矿泉水×18(¥90.00)、双中支中华×1(¥72.00)、阿萨姆×1(¥8.00)(商品合计¥170.00 占比5.2%);综合:10-12月到店消费12天/15次,到店周期中位#6,消费排名#43,在店时长#24;12月到店消费2天/3次,到店周期中位#5,消费排名#43,在店时长#35;最近到店2025-12-16;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+44,刘哥,135****0020,婉婉(5.3h)、球球(2.1h),3036.80,0.00,371.51,订单:2单,平均单次¥1518.40;打球:5.0h,平均单次2.5h;偏好:包厢(93.4%)、S区/斯诺克(6.6%)、补时长(0.0%);时间:到店均值11:33 中位11:33;离店均值12:15 中位12:15;商品:百威235毫升×79(¥1185.00)、中支芙蓉王×2(¥76.00)、地道肠×6(¥30.00)、鱼蛋×6(¥30.00)、红利群×1(¥26.00)、红烧牛肉面×2(¥24.00)(商品合计¥1417.00 占比46.7%);综合:10-12月到店消费2天/2次,到店周期中位#20,消费排名#44,在店时长#66;12月到店消费1天/1次,到店周期中位—,消费排名#44,在店时长#49;最近到店2025-12-17;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+45,李先生,131****4000,小敌(11.8h)、涛涛(2.1h)、Amy(1.1h),2997.53,3000.00,563.47,订单:4单,平均单次¥749.38;打球:11.8h,平均单次3.0h;偏好:包厢(100.0%);时间:到店均值16:24 中位20:21;离店均值19:21 中位23:11;商品:轻上椰子水×10(¥120.00)、科罗娜啤酒275ml×6(¥108.00)、跨越贵烟×1(¥28.00)、地道肠×2(¥10.00)、海之言×1(¥8.00)、茶兀×1(¥8.00)(商品合计¥298.00 占比9.9%);综合:10-12月到店消费3天/4次,到店周期中位#5,消费排名#45,在店时长#48;12月到店消费0天/0次,到店周期中位—,消费排名#45,在店时长—;最近到店2025-11-07;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+46,阿亮,159****2628,涛涛(9.1h)、素素(3.1h)、奈千(2.9h)、梦梦(2.7h)、柚子(2.4h),2936.26,0.00,612.33,订单:8单,平均单次¥367.03;打球:16.8h,平均单次2.1h;偏好:B区(65.3%)、S区/斯诺克(34.5%)、补时长(0.2%);时间:到店均值21:06 中位20:32;离店均值23:26 中位23:29;商品:哇哈哈矿泉水×4(¥20.00)、香飘飘果汁茶×1(¥10.00)、茶兀×1(¥8.00)(商品合计¥38.00 占比1.3%);综合:10-12月到店消费6天/8次,到店周期中位#1,消费排名#46,在店时长#43;12月到店消费2天/3次,到店周期中位#1,消费排名#46,在店时长#29;最近到店2025-12-04;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+47,李先生,186****8308,小侯(5.6h)、年糕(4.2h),2785.23,0.00,0.00,订单:1单,平均单次¥2785.23;打球:8.3h,平均单次8.3h;偏好:包厢(100.0%);时间:到店均值23:15 中位23:15;离店均值次日07:32 中位次日07:32;商品:清洁费150×1(¥150.00)、卡士×1(¥22.00)、合味道泡面×1(¥12.00)、轻上椰子水×1(¥12.00)、雪碧×2(¥10.00)、哇哈哈矿泉水×1(¥5.00)(商品合计¥216.00 占比7.8%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#47,在店时长#55;12月到店消费0天/0次,到店周期中位—,消费排名#47,在店时长—;最近到店2025-11-28;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+48,周先生,173****7775,乔西(7.5h)、小敌(6.6h),2726.01,0.00,0.00,订单:1单,平均单次¥2726.01;打球:7.5h,平均单次7.5h;偏好:666(100.0%);时间:到店均值15:40 中位15:40;离店均值23:11 中位23:11;商品:哇哈哈矿泉水×1(¥5.00)(商品合计¥5.00 占比0.2%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#48,在店时长#58;12月到店消费0天/0次,到店周期中位—,消费排名#48,在店时长—;最近到店2025-10-25;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+49,林先生,159****0021,婉婉(12.0h)、小柔(3.2h)、苏苏(3.1h),2690.52,0.00,49.48,订单:2单,平均单次¥1345.26;打球:6.0h,平均单次3.0h;偏好:包厢(66.7%)、A区(33.3%);时间:到店均值10:13 中位10:13;离店均值12:14 中位12:14;商品:百威235毫升×24(¥360.00)、中支芙蓉王×2(¥76.00)、绿茶×4(¥24.00)、无穷爱辣烤鸡爪×1(¥20.00)、透明袋无穷鸡翅×1(¥20.00)、益达×1(¥18.00)(商品合计¥597.00 占比22.2%);综合:10-12月到店消费2天/2次,到店周期中位#6,消费排名#49,在店时长#62;12月到店消费0天/0次,到店周期中位—,消费排名#49,在店时长—;最近到店2025-11-25;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+50,周先生,193****6822,千千(8.6h)、素素(6.2h),2643.64,0.00,2092.01,订单:3单,平均单次¥881.21;打球:14.9h,平均单次5.0h;偏好:C区(100.0%);时间:到店均值21:06 中位22:21;离店均值次日02:04 中位次日02:07;商品:哇哈哈矿泉水×5(¥25.00)、卡士×1(¥22.00)、东方树叶×2(¥16.00)、王老吉×1(¥8.00)、美汁源果粒橙×1(¥8.00)、一次性拖鞋×1(¥5.00)(商品合计¥89.00 占比3.4%);综合:10-12月到店消费3天/3次,到店周期中位#4,消费排名#50,在店时长#44;12月到店消费3天/3次,到店周期中位#4,消费排名#50,在店时长#21;最近到店2025-12-13;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+51,林先生,188****0332,周周(4.0h)、小敌(1.9h),2612.01,0.00,0.00,订单:8单,平均单次¥326.50;打球:16.9h,平均单次2.1h;偏好:666(25.1%)、麻将(22.3%)、M7(20.7%)、S区/斯诺克(12.8%);时间:到店均值14:55 中位17:06;离店均值17:17 中位19:13;商品:钻石荷花×3(¥135.00)、50枸杞槟榔×1(¥65.00)、跨越贵烟×1(¥28.00)、哇哈哈矿泉水×5(¥25.00)、红牛×2(¥20.00)、蜂蜜水×2(¥20.00)(商品合计¥330.00 占比12.6%);综合:10-12月到店消费6天/8次,到店周期中位#1,消费排名#51,在店时长#42;12月到店消费0天/0次,到店周期中位—,消费排名#51,在店时长—;最近到店2025-11-28;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+52,牛先生,152****5159,柚子(10.4h),2187.48,0.00,0.00,订单:5单,平均单次¥437.50;打球:10.4h,平均单次2.1h;偏好:C区(99.8%)、补时长(0.2%)、A区(0.0%)、B区(0.0%);时间:到店均值19:00 中位19:37;离店均值21:29 中位20:52;商品:地道肠×6(¥30.00)、东方树叶×2(¥16.00)、美汁源果粒橙×2(¥16.00)(商品合计¥62.00 占比2.8%);综合:10-12月到店消费3天/5次,到店周期中位#1,消费排名#52,在店时长#51;12月到店消费0天/0次,到店周期中位—,消费排名#52,在店时长—;最近到店2025-11-24;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+53,孟紫龙(该会员已注销),176****37411,,2131.72,0.00,0.00,订单:7单,平均单次¥304.53;打球:26.3h,平均单次3.8h;偏好:C区(99.9%)、补时长(0.1%);时间:到店均值19:17 中位19:34;离店均值23:32 中位23:56;商品:可乐×5(¥25.00)、东鹏特饮×2(¥14.00)、鱼蛋×1(¥5.00)、一次性手套×1(¥2.00)(商品合计¥46.00 占比2.2%);综合:10-12月到店消费7天/7次,到店周期中位#4,消费排名#53,在店时长#28;12月到店消费0天/0次,到店周期中位—,消费排名#53,在店时长—;最近到店2025-11-28;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+54,罗超杰,137****8012,苏苏(2.1h)、素素(1.9h)、周周(1.2h)、球球(0.8h),1584.05,0.00,3037.00,订单:8单,平均单次¥198.01;打球:8.4h,平均单次1.0h;偏好:包厢(74.8%)、B区(14.0%)、A区(10.9%)、补时长(0.2%);时间:到店均值18:55 中位22:56;离店均值20:06 中位23:23;商品:雪碧×4(¥20.00)、可乐×3(¥15.00)、维他柠檬茶×1(¥8.00)、打火机×1(¥2.00)(商品合计¥45.00 占比2.8%);综合:10-12月到店消费6天/8次,到店周期中位#3,消费排名#54,在店时长#54;12月到店消费0天/0次,到店周期中位—,消费排名#54,在店时长—;最近到店2025-11-05;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+55,汪先生,139****6339,姜姜(9.6h),1390.07,1000.00,11.99,订单:4单,平均单次¥347.52;打球:5.1h,平均单次1.3h;偏好:包厢(82.3%)、A区(17.4%)、补时长(0.4%);时间:到店均值21:16 中位22:01;离店均值23:26 中位23:25;商品:轻上椰子水×1(¥12.00)、三得利×1(¥8.00)、巧乐兹伊利×1(¥8.00)(商品合计¥28.00 占比2.0%);综合:10-12月到店消费3天/4次,到店周期中位#1,消费排名#55,在店时长#65;12月到店消费0天/0次,到店周期中位—,消费排名#55,在店时长—;最近到店2025-10-09;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+56,桂先生(该会员已注销),166****72751,,1370.81,0.00,0.00,订单:5单,平均单次¥274.16;打球:19.0h,平均单次3.8h;偏好:C区(100.0%);时间:到店均值19:20 中位19:37;离店均值23:08 中位23:57;商品:红牛×4(¥40.00)、东鹏特饮×2(¥14.00)、可乐×2(¥10.00)、地道肠×2(¥10.00)、普通扑克×1(¥5.00)(商品合计¥79.00 占比5.8%);综合:10-12月到店消费5天/5次,到店周期中位#2,消费排名#56,在店时长#39;12月到店消费0天/0次,到店周期中位—,消费排名#56,在店时长—;最近到店2025-10-16;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+57,方先生,153****3185,乔西(3.2h),1313.30,1000.00,0.00,订单:3单,平均单次¥437.77;打球:10.2h,平均单次3.4h;偏好:麻将(69.0%)、666(31.0%);时间:到店均值17:32 中位17:19;离店均值21:01 中位20:30;商品:农夫山泉苏打水×5(¥30.00)、掼蛋扑克×2(¥16.00)、可乐×3(¥15.00)、普通扑克×2(¥10.00)、红牛×1(¥10.00)、椰汁×1(¥8.00)(商品合计¥100.00 占比7.6%);综合:10-12月到店消费3天/3次,到店周期中位#10,消费排名#57,在店时长#52;12月到店消费0天/0次,到店周期中位—,消费排名#57,在店时长—;最近到店2025-11-17;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:关注是否为临时充值型,建议引导储值梯度与权益
+58,陈淑涛,132****5485,涛涛(4.4h)、乔西(3.4h),1276.77,0.00,0.00,订单:3单,平均单次¥425.59;打球:4.4h,平均单次1.5h;偏好:麻将(77.1%)、A区(22.9%)、补时长(0.0%);时间:到店均值12:52 中位09:40;离店均值14:39 中位10:40;商品:细荷花×1(¥50.00)、轻上椰子水×1(¥12.00)、哇哈哈矿泉水×2(¥10.00)、火鸡面×1(¥10.00)、茶兀×1(¥8.00)、火腿肠×1(¥5.00)(商品合计¥99.00 占比7.8%);综合:10-12月到店消费2天/3次,到店周期中位#7,消费排名#58,在店时长#69;12月到店消费0天/0次,到店周期中位—,消费排名#58,在店时长—;最近到店2025-11-22;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+59,清,130****3087,小侯(3.0h)、阿清(3.0h)、千千(3.0h),1128.06,0.00,1944.76,订单:1单,平均单次¥1128.06;打球:3.0h,平均单次3.0h;偏好:麻将(100.0%);时间:到店均值21:18 中位21:18;离店均值次日02:00 中位次日02:00;综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#59,在店时长#73;12月到店消费1天/1次,到店周期中位—,消费排名#59,在店时长#38;最近到店2025-12-08;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+60,amy,137****8221,Amy(4.8h),1105.90,0.00,0.38,订单:1单,平均单次¥1105.90;打球:4.8h,平均单次4.8h;偏好:麻将(100.0%);时间:到店均值22:47 中位22:47;离店均值次日03:37 中位次日03:37;商品:跨越贵烟×2(¥60.00)、掼蛋扑克×2(¥16.00)、热水可续杯×4(¥12.00)、可乐×2(¥10.00)、蜂蜜水×1(¥10.00)(商品合计¥108.00 占比9.8%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#60,在店时长#67;12月到店消费1天/1次,到店周期中位—,消费排名#60,在店时长#32;最近到店2025-12-06;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+61,曾先生,133****1235,奈千(1.0h),991.34,0.00,303.19,订单:7单,平均单次¥141.62;打球:13.0h,平均单次1.9h;偏好:S区/斯诺克(63.2%)、A区(36.8%);时间:到店均值13:58 中位12:19;离店均值15:49 中位14:10;商品:咖啡代购×3(¥45.00)、东方树叶×3(¥24.00)、屈臣氏苏打水×1(¥8.00)、阿萨姆×1(¥8.00)、绿茶×1(¥6.00)、哇哈哈矿泉水×1(¥5.00)(商品合计¥98.00 占比9.9%);综合:10-12月到店消费7天/7次,到店周期中位#6,消费排名#61,在店时长#45;12月到店消费2天/2次,到店周期中位#6,消费排名#61,在店时长#36;最近到店2025-12-10;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+62,昌哥,137****1229,Amy(2.0h)、小柔(1.8h)、苏苏(1.7h),942.42,0.00,2471.98,订单:2单,平均单次¥471.21;打球:4.5h,平均单次2.3h;偏好:A区(100.0%);时间:到店均值20:05 中位20:05;离店均值22:21 中位22:21;商品:农夫山泉苏打水×3(¥18.00)、麻辣王子×1(¥12.00)、哇哈哈矿泉水×2(¥10.00)、营养快线×1(¥8.00)、阿萨姆×1(¥8.00)(商品合计¥56.00 占比5.9%);综合:10-12月到店消费2天/2次,到店周期中位#15,消费排名#62,在店时长#68;12月到店消费1天/1次,到店周期中位—,消费排名#62,在店时长#44;最近到店2025-12-07;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+63,李,131****9882,,927.44,0.00,0.00,订单:11单,平均单次¥84.31;打球:11.1h,平均单次1.0h;偏好:B区(68.7%)、A区(30.9%)、补时长(0.4%);时间:到店均值13:13 中位13:14;离店均值14:13 中位14:00;商品:哇哈哈矿泉水×4(¥20.00)(商品合计¥20.00 占比2.2%);综合:10-12月到店消费6天/11次,到店周期中位#8,消费排名#63,在店时长#49;12月到店消费0天/0次,到店周期中位—,消费排名#63,在店时长—;最近到店2025-11-24;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+64,邓飛,136****9597,婉婉(6.8h)、苏苏(6.0h)、小敌(4.5h)、小柔(1.2h)、球球(0.8h),925.47,2345.00,74.77,订单:1单,平均单次¥925.47;打球:1.9h,平均单次1.9h;偏好:包厢(100.0%);时间:到店均值01:56 中位01:56;离店均值03:48 中位03:48;商品:百威235毫升×12(¥180.00)、卡士×1(¥22.00)、农夫山泉苏打水×3(¥18.00)、一次性拖鞋×1(¥5.00)、哇哈哈矿泉水×1(¥5.00)(商品合计¥230.00 占比24.9%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#64,在店时长#85;12月到店消费0天/0次,到店周期中位—,消费排名#64,在店时长—;最近到店2025-11-09;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+65,陈世,134****1938,瑶瑶(0.8h),921.09,0.00,0.00,订单:6单,平均单次¥153.52;打球:6.5h,平均单次1.1h;偏好:C区(49.7%)、S区/斯诺克(49.6%)、补时长(0.7%);时间:到店均值20:42 中位21:08;离店均值22:16 中位22:24;综合:10-12月到店消费3天/6次,到店周期中位#24,消费排名#65,在店时长#61;12月到店消费0天/0次,到店周期中位—,消费排名#65,在店时长—;最近到店2025-11-20;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+66,婉婉,183****2742,婉婉(4.3h),867.49,1000.00,514.08,订单:2单,平均单次¥433.74;打球:4.4h,平均单次2.2h;偏好:B区(36.5%)、A区(35.9%)、888(27.6%);时间:到店均值15:41 中位15:41;离店均值18:01 中位18:01;商品:旺仔牛奶×2(¥20.00)、红牛×1(¥10.00)、王老吉×1(¥8.00)、哇哈哈矿泉水×1(¥5.00)、喜之郎果冻×1(¥5.00)(商品合计¥48.00 占比5.5%);综合:10-12月到店消费2天/2次,到店周期中位#23,消费排名#66,在店时长#70;12月到店消费0天/0次,到店周期中位—,消费排名#66,在店时长—;最近到店2025-11-21;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+67,贺斌,150****0885,佳怡(1.0h),770.56,0.00,0.00,订单:4单,平均单次¥192.64;打球:9.6h,平均单次2.4h;偏好:A区(50.1%)、C区(49.9%);时间:到店均值17:30 中位17:55;离店均值19:53 中位19:54;商品:细荷花×1(¥50.00)、可乐×5(¥25.00)、哇哈哈矿泉水×2(¥10.00)、地道肠×2(¥10.00)、东方树叶×1(¥8.00)(商品合计¥103.00 占比13.4%);综合:10-12月到店消费3天/4次,到店周期中位#4,消费排名#67,在店时长#53;12月到店消费0天/0次,到店周期中位—,消费排名#67,在店时长—;最近到店2025-11-03;趋势:10-12月到店频次下降,建议重点唤醒;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+68,陈泽斌,132****6060,,700.00,0.00,0.00,订单:6单,平均单次¥116.67;打球:0.1h,平均单次0.0h;偏好:补时长(100.0%);时间:到店均值17:51 中位20:40;离店均值18:50 中位21:39;综合:10-12月到店消费6天/6次,到店周期中位#10,消费排名#68,在店时长#97;12月到店消费1天/1次,到店周期中位—,消费排名#68,在店时长#51;最近到店2025-12-11;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+69,林总,138****1180,周周(2.2h)、婉婉(0.9h),684.44,0.00,16729.21,订单:2单,平均单次¥342.22;打球:3.7h,平均单次1.9h;偏好:包厢(100.0%);时间:到店均值18:28 中位18:28;离店均值20:20 中位20:20;商品:东方树叶×1(¥8.00)、哇哈哈AD钙奶×1(¥8.00)(商品合计¥16.00 占比2.3%);综合:10-12月到店消费2天/2次,到店周期中位#2,消费排名#69,在店时长#72;12月到店消费0天/0次,到店周期中位—,消费排名#69,在店时长—;最近到店2025-11-25;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额充足,可提供包厢/团建档期与专属权益;重点维护包厢/团建需求,提前锁档与套餐化
+70,卢广贤,186****6220,,680.44,0.00,0.00,订单:4单,平均单次¥170.11;打球:10.4h,平均单次2.6h;偏好:B区(62.8%)、C区(37.2%);时间:到店均值18:15 中位18:45;离店均值20:51 中位20:41;商品:轻上椰子水×1(¥12.00)、三得利×1(¥8.00)、东鹏特饮×1(¥7.00)、冰红茶×1(¥6.00)、普通扑克×1(¥5.00)(商品合计¥38.00 占比5.6%);综合:10-12月到店消费4天/4次,到店周期中位#18,消费排名#70,在店时长#50;12月到店消费1天/1次,到店周期中位—,消费排名#70,在店时长#46;最近到店2025-12-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+71,王龙,186****8011,,669.58,0.00,95.20,订单:4单,平均单次¥167.40;打球:7.8h,平均单次2.0h;偏好:麻将(99.7%)、补时长(0.3%);时间:到店均值20:56 中位21:02;离店均值23:28 中位23:28;商品:麻将房茶位费×2(¥80.00)、东方树叶×2(¥16.00)(商品合计¥96.00 占比14.3%);综合:10-12月到店消费2天/4次,到店周期中位#9,消费排名#71,在店时长#56;12月到店消费2天/4次,到店周期中位#7,消费排名#71,在店时长#28;最近到店2025-12-12;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+72,王先生,185****1125,,600.68,0.00,0.00,订单:4单,平均单次¥150.17;打球:5.9h,平均单次1.5h;偏好:S区/斯诺克(99.4%)、补时长(0.6%);时间:到店均值18:13 中位18:31;离店均值20:09 中位19:30;商品:哇哈哈矿泉水×1(¥5.00)(商品合计¥5.00 占比0.8%);综合:10-12月到店消费4天/4次,到店周期中位#6,消费排名#72,在店时长#63;12月到店消费1天/1次,到店周期中位—,消费排名#72,在店时长#43;最近到店2025-12-02;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+73,潘先生,186****0511,年糕(2.0h),564.93,0.00,0.00,订单:2单,平均单次¥282.46;打球:3.0h,平均单次1.5h;偏好:666(66.7%)、A区(33.3%);时间:到店均值18:28 中位18:28;离店均值19:29 中位19:29;商品:农夫山泉苏打水×1(¥6.00)(商品合计¥6.00 占比1.1%);综合:10-12月到店消费2天/2次,到店周期中位#11,消费排名#73,在店时长#75;12月到店消费2天/2次,到店周期中位#8,消费排名#73,在店时长#40;最近到店2025-12-13;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+74,老宋,138****4554,婉婉(1.0h)、欣怡(0.5h),541.97,0.00,2126.14,订单:2单,平均单次¥270.98;打球:1.5h,平均单次0.7h;偏好:888(66.9%)、A区(33.1%);时间:到店均值19:24 中位19:24;离店均值20:02 中位20:02;商品:百威235毫升×12(¥180.00)(商品合计¥180.00 占比33.2%);综合:10-12月到店消费2天/2次,到店周期中位#13,消费排名#74,在店时长#91;12月到店消费0天/0次,到店周期中位—,消费排名#74,在店时长—;最近到店2025-11-07;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+75,郭先生,156****5001,希希(1.6h),518.35,0.00,2.57,订单:2单,平均单次¥259.18;打球:7.1h,平均单次3.5h;偏好:A区(100.0%);时间:到店均值20:53 中位20:53;离店均值次日00:32 中位次日00:32;商品:可乐×2(¥10.00)、普通扑克×2(¥10.00)、一次性手套×2(¥4.00)(商品合计¥24.00 占比4.6%);综合:10-12月到店消费2天/2次,到店周期中位#7,消费排名#75,在店时长#60;12月到店消费0天/0次,到店周期中位—,消费排名#75,在店时长—;最近到店2025-11-01;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+76,孙启明,137****6325,,500.00,0.00,0.00,订单:4单,平均单次¥125.00;打球:2.0h,平均单次0.5h;偏好:补时长(100.0%);时间:到店均值10:50 中位09:58;离店均值11:49 中位10:57;综合:10-12月到店消费4天/4次,到店周期中位#16,消费排名#76,在店时长#83;12月到店消费0天/0次,到店周期中位—,消费排名#76,在店时长—;最近到店2025-11-19;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+77,王先生,136****0168,,500.00,0.00,0.00,订单:5单,平均单次¥100.00;打球:0.1h,平均单次0.0h;偏好:补时长(100.0%);时间:到店均值19:45 中位19:22;离店均值20:44 中位20:21;综合:10-12月到店消费4天/5次,到店周期中位#5,消费排名#77,在店时长#98;12月到店消费1天/1次,到店周期中位—,消费排名#77,在店时长#53;最近到店2025-12-03;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+78,黎先生,133****0983,奈千(1.7h)、婉婉(0.8h),470.19,0.00,0.00,订单:1单,平均单次¥470.19;打球:1.7h,平均单次1.7h;偏好:包厢(100.0%);时间:到店均值19:17 中位19:17;离店均值21:01 中位21:01;商品:王老吉×2(¥16.00)、普通茶位×1(¥10.00)、香飘飘果汁茶×1(¥10.00)(商品合计¥36.00 占比7.7%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#78,在店时长#89;12月到店消费0天/0次,到店周期中位—,消费排名#78,在店时长—;最近到店2025-10-10;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+79,常总,185****7188,年糕(1.7h)、阿清(1.7h),460.52,0.00,5000.00,订单:1单,平均单次¥460.52;打球:1.8h,平均单次1.8h;偏好:A区(100.0%);时间:到店均值19:13 中位19:13;离店均值20:58 中位20:58;商品:哇哈哈矿泉水×2(¥10.00)、脉动×1(¥8.00)(商品合计¥18.00 占比3.9%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#79,在店时长#88;12月到店消费1天/1次,到店周期中位—,消费排名#79,在店时长#47;最近到店2025-12-14;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+80,张丹逸,136****6637,,439.36,0.00,0.00,订单:4单,平均单次¥109.84;打球:2.4h,平均单次0.6h;偏好:B区(99.0%)、补时长(1.0%);时间:到店均值11:15 中位10:29;离店均值12:36 中位11:29;综合:10-12月到店消费4天/4次,到店周期中位#1,消费排名#80,在店时长#80;12月到店消费1天/1次,到店周期中位—,消费排名#80,在店时长#55;最近到店2025-12-03;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+81,陈先生,186****8238,乔西(1.8h),416.17,0.00,497.83,订单:1单,平均单次¥416.17;打球:1.8h,平均单次1.8h;偏好:包厢(100.0%);时间:到店均值21:15 中位21:15;离店均值23:04 中位23:04;商品:普通茶位×3(¥30.00)(商品合计¥30.00 占比7.2%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#81,在店时长#86;12月到店消费0天/0次,到店周期中位—,消费排名#81,在店时长—;最近到店2025-11-20;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导;重点维护包厢/团建需求,提前锁档与套餐化
+82,陈先生,138****3964,,400.00,0.00,0.00,订单:3单,平均单次¥133.33;打球:2.5h,平均单次0.8h;偏好:补时长(100.0%);时间:到店均值15:17 中位21:41;离店均值15:57 中位22:40;综合:10-12月到店消费3天/3次,到店周期中位#24,消费排名#82,在店时长#79;12月到店消费1天/1次,到店周期中位—,消费排名#82,在店时长#52;最近到店2025-12-04;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+83,张先生,136****4528,,398.35,0.00,0.00,订单:3单,平均单次¥132.78;打球:2.9h,平均单次1.0h;偏好:S区/斯诺克(98.8%)、补时长(1.2%);时间:到店均值21:05 中位20:51;离店均值22:41 中位22:13;商品:农夫山泉苏打水×1(¥6.00)(商品合计¥6.00 占比1.5%);综合:10-12月到店消费3天/3次,到店周期中位#15,消费排名#83,在店时长#76;12月到店消费2天/2次,到店周期中位#10,消费排名#83,在店时长#42;最近到店2025-12-17;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+84,小宇,187****8077,球球(1.5h)、悦悦(0.4h),397.50,0.00,936.07,订单:2单,平均单次¥198.75;打球:2.1h,平均单次1.0h;偏好:包厢(80.9%)、TV台(19.1%);时间:到店均值18:07 中位18:07;离店均值19:09 中位19:09;商品:哇哈哈AD钙奶×1(¥8.00)、农夫山泉苏打水×1(¥6.00)、哇哈哈矿泉水×1(¥5.00)(商品合计¥19.00 占比4.8%);综合:10-12月到店消费2天/2次,到店周期中位#9,消费排名#84,在店时长#82;12月到店消费0天/0次,到店周期中位—,消费排名#84,在店时长—;最近到店2025-10-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:重点维护包厢/团建需求,提前锁档与套餐化
+85,黄先生,191****8219,,364.33,0.00,0.00,订单:4单,平均单次¥91.08;打球:1.2h,平均单次0.3h;偏好:B区(95.4%)、补时长(4.6%);时间:到店均值22:45 中位22:43;离店均值23:46 中位23:45;综合:10-12月到店消费3天/4次,到店周期中位#4,消费排名#85,在店时长#93;12月到店消费0天/0次,到店周期中位—,消费排名#85,在店时长—;最近到店2025-11-29;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+86,刘女士,177****7538,,362.58,0.00,0.00,订单:4单,平均单次¥90.64;打球:2.8h,平均单次0.7h;偏好:B区(99.3%)、补时长(0.7%);时间:到店均值15:53 中位15:44;离店均值17:04 中位17:04;综合:10-12月到店消费1天/4次,到店周期中位—,消费排名#86,在店时长#77;12月到店消费0天/0次,到店周期中位—,消费排名#86,在店时长—;最近到店2025-10-14;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+87,魏先生,137****6862,,319.39,0.00,84.51,订单:1单,平均单次¥319.39;打球:5.4h,平均单次5.4h;偏好:A区(66.1%)、S区/斯诺克(33.9%)、B区(0.0%);时间:到店均值18:44 中位18:44;离店均值次日00:08 中位次日00:08;商品:维他柠檬茶×2(¥16.00)、东方树叶×1(¥8.00)(商品合计¥24.00 占比7.5%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#87,在店时长#64;12月到店消费1天/1次,到店周期中位—,消费排名#87,在店时长#30;最近到店2025-12-05;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+88,杜先生,188****4705,,307.47,0.00,0.00,订单:3单,平均单次¥102.49;打球:2.1h,平均单次0.7h;偏好:A区(98.3%)、补时长(1.7%);时间:到店均值21:25 中位21:44;离店均值22:45 中位22:43;商品:哇哈哈矿泉水×2(¥10.00)(商品合计¥10.00 占比3.3%);综合:10-12月到店消费2天/3次,到店周期中位#21,消费排名#88,在店时长#81;12月到店消费0天/0次,到店周期中位—,消费排名#88,在店时长—;最近到店2025-11-02;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+89,刘先生,137****2930,,300.00,0.00,1.27,订单:1单,平均单次¥300.00;打球:0.0h,平均单次0.0h;偏好:补时长(100.0%);时间:到店均值23:47 中位23:47;离店均值次日00:48 中位次日00:48;综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#89,在店时长#100;12月到店消费1天/1次,到店周期中位—,消费排名#89,在店时长#54;最近到店2025-12-07;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+90,陈先生,133****6117,,300.00,0.00,0.00,订单:2单,平均单次¥150.00;打球:0.0h,平均单次0.0h;偏好:补时长(100.0%);时间:到店均值20:50 中位20:50;离店均值21:49 中位21:49;综合:10-12月到店消费2天/2次,到店周期中位#2,消费排名#90,在店时长#99;12月到店消费0天/0次,到店周期中位—,消费排名#90,在店时长—;最近到店2025-11-21;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+91,潘先生,176****7964,,300.00,0.00,0.00,订单:1单,平均单次¥300.00;打球:3.0h,平均单次3.0h;偏好:补时长(100.0%);时间:到店均值00:03 中位00:03;离店均值00:03 中位00:03;综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#91,在店时长#74;12月到店消费1天/1次,到店周期中位—,消费排名#91,在店时长#39;最近到店2025-12-19;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+92,钟智豪,188****2803,小侯(1.8h),274.34,0.00,0.00,订单:1单,平均单次¥274.34;打球:1.8h,平均单次1.8h;偏好:A区(100.0%);时间:到店均值23:50 中位23:50;离店均值次日01:36 中位次日01:36;综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#92,在店时长#87;12月到店消费0天/0次,到店周期中位—,消费排名#92,在店时长—;最近到店2025-11-28;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+93,都先生,138****7796,素素(1.6h),269.64,0.00,0.00,订单:1单,平均单次¥269.64;打球:1.6h,平均单次1.6h;偏好:B区(100.0%);时间:到店均值15:17 中位15:17;离店均值16:56 中位16:56;商品:东方树叶×1(¥8.00)、哇哈哈AD钙奶×1(¥8.00)(商品合计¥16.00 占比5.9%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#93,在店时长#90;12月到店消费0天/0次,到店周期中位—,消费排名#93,在店时长—;最近到店2025-11-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+94,林志铭,135****4233,小侯(1.2h),267.96,0.00,795.66,订单:3单,平均单次¥89.32;打球:2.0h,平均单次0.7h;偏好:TV台(75.2%)、S区/斯诺克(24.8%);时间:到店均值19:45 中位20:54;离店均值20:24 中位21:40;综合:10-12月到店消费2天/3次,到店周期中位#12,消费排名#94,在店时长#84;12月到店消费0天/0次,到店周期中位—,消费排名#94,在店时长—;最近到店2025-11-30;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+95,方先生,158****6447,,248.00,0.00,0.00,订单:3单,平均单次¥82.67;打球:1.0h,平均单次0.3h;偏好:A区(97.2%)、补时长(2.8%);时间:到店均值15:35 中位22:11;离店均值16:15 中位23:11;综合:10-12月到店消费3天/3次,到店周期中位#17,消费排名#95,在店时长#94;12月到店消费2天/2次,到店周期中位#2,消费排名#95,在店时长#48;最近到店2025-12-18;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+96,李先生,176****5124,,244.00,0.00,0.00,订单:3单,平均单次¥81.33;打球:0.9h,平均单次0.3h;偏好:A区(97.8%)、补时长(2.2%);时间:到店均值20:59 中位21:28;离店均值21:39 中位21:28;综合:10-12月到店消费3天/3次,到店周期中位#5,消费排名#96,在店时长#95;12月到店消费0天/0次,到店周期中位—,消费排名#96,在店时长—;最近到店2025-10-13;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+97,钟先生,132****3438,,239.37,0.00,0.00,订单:1单,平均单次¥239.37;打球:2.6h,平均单次2.6h;偏好:麻将(100.0%);时间:到店均值19:32 中位19:32;离店均值22:10 中位22:10;商品:50枸杞槟榔×1(¥65.00)、地道肠×3(¥15.00)、哇哈哈矿泉水×2(¥10.00)、蜂蜜水×1(¥10.00)、屈臣氏苏打水×1(¥8.00)、芬达×1(¥5.00)(商品合计¥113.00 占比47.2%);综合:10-12月到店消费1天/1次,到店周期中位—,消费排名#97,在店时长#78;12月到店消费0天/0次,到店周期中位—,消费排名#97,在店时长—;最近到店2025-10-20;趋势:到店频次波动,建议按常用时段做稳定触达;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
+98,杨,130****5960,,232.00,0.00,287.50,订单:2单,平均单次¥116.00;打球:4.0h,平均单次2.0h;偏好:B区(100.0%);时间:到店均值18:09 中位18:09;离店均值20:11 中位20:11;综合:10-12月到店消费2天/2次,到店周期中位#2,消费排名#98,在店时长#71;12月到店消费2天/2次,到店周期中位#2,消费排名#98,在店时长#33;最近到店2025-12-05;趋势:10-12月到店频次上升,12月更活跃;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+99,黄国磊,131****3045,,225.33,0.00,0.22,订单:3单,平均单次¥75.11;打球:0.1h,平均单次0.0h;偏好:A区(85.5%)、补时长(14.5%);时间:到店均值17:56 中位18:02;离店均值18:36 中位18:19;商品:蜂蜜水×2(¥20.00)(商品合计¥20.00 占比8.9%);综合:10-12月到店消费3天/3次,到店周期中位#22,消费排名#99,在店时长#96;12月到店消费1天/1次,到店周期中位—,消费排名#99,在店时长#55;最近到店2025-12-12;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:储值余额偏低,建议在其常用时段做补能引导
+100,周先生,159****9997,,200.00,0.00,0.00,订单:2单,平均单次¥100.00;打球:1.2h,平均单次0.6h;偏好:补时长(100.0%);时间:到店均值02:54 中位02:54;离店均值03:19 中位03:19;综合:10-12月到店消费2天/2次,到店周期中位#2,消费排名#100,在店时长#92;12月到店消费1天/1次,到店周期中位—,消费排名#100,在店时长#50;最近到店2025-12-01;趋势:12月为高峰月,具备加深运营空间;围客与客户运营建议:保持常用时段的稳定服务供给,提升复购粘性
diff --git a/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.md b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.md
new file mode 100644
index 0000000..826151c
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/客户_Top100_2025年10-12月_总表.md
@@ -0,0 +1,459 @@
+# 2025年10-12月 客户消费能力Top100(总表)
+## 思考过程
+以台费订单为基准汇总三类明细,满足应付金额口径,并输出Top100客户的消费/充值/助教偏好。按你的要求,先生成评价为空的版本,再在脚本末尾回填评价。
+
+## 查询说明
+消费=台费(dwd_table_fee_log.ledger_amount)+助教(dwd_assistant_service_log.ledger_amount)+商品(dwd_store_goods_sale.ledger_amount),均为应付金额(不扣优惠),以台费订单为基准串联;充值=充值支付流水(dwd_payment.relate_type=5, pay_status=2, pay_amount>0)按支付时间切月;储值卡未使用金额=当前有效储值卡余额之和(dim_member_card_account.balance, member_card_type_name='储值卡');喜爱助教=基础课时长+附加课时长*1.5(income_seconds换算小时),总表按10-12月汇总Top5。
+
+## SQL
+
+### Top100(按消费总额)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+select
+ o.member_id,
+ sum(o.order_amount) as consume_total,
+ count(*) as order_cnt
+from orders o
+where o.member_id is not null and o.member_id <> 0
+group by o.member_id
+order by consume_total desc
+limit 100;
+```
+
+### 按月消费汇总
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, x as (
+ select
+ o.member_id,
+ case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ o.order_amount
+ from orders o
+ where o.member_id is not null and o.member_id <> 0
+)
+select
+ member_id,
+ month_key,
+ sum(order_amount) as consume_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+```
+
+### 按月充值汇总
+```sql
+with pay as (
+ select
+ p.pay_time,
+ r.member_id,
+ p.pay_amount
+ from billiards_dwd.dwd_payment p
+ join billiards_dwd.dwd_recharge_order r on r.recharge_order_id = p.relate_id
+ where p.site_id = %(site_id)s
+ and p.relate_type = 5
+ and p.pay_status = 2
+ and p.pay_amount > 0
+ and p.pay_time >= %(window_start)s::timestamptz
+ and p.pay_time < %(window_end)s::timestamptz
+)
+, x as (
+ select
+ member_id,
+ case when pay_time >= '2025-10-01 00:00:00+08'::timestamptz and pay_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when pay_time >= '2025-11-01 00:00:00+08'::timestamptz and pay_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when pay_time >= '2025-12-01 00:00:00+08'::timestamptz and pay_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ pay_amount
+ from pay
+)
+select
+ member_id,
+ month_key,
+ sum(pay_amount) as recharge_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+```
+
+### 储值卡未使用金额(当前余额汇总)
+```sql
+select
+ tenant_member_id as member_id,
+ sum(balance) as stored_value_balance
+from billiards_dwd.dim_member_card_account
+where scd2_is_current=1
+ and coalesce(is_delete,0)=0
+ and member_card_type_name='储值卡'
+ and tenant_member_id = any(%(ids)s)
+group by tenant_member_id;
+```
+
+### 喜爱助教Top5(10-12月)
+```sql
+with x as (
+ select
+ asl.tenant_member_id as member_id,
+ asl.nickname as assistant_nickname,
+ sum(case when asl.order_assistant_type=1 then asl.income_seconds else asl.income_seconds*1.5 end) / 3600.0 as weighted_hours
+ from billiards_dwd.dwd_assistant_service_log asl
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0)=0
+ and asl.tenant_member_id is not null and asl.tenant_member_id <> 0
+ and asl.start_use_time >= %(window_start)s::timestamptz
+ and asl.start_use_time < %(window_end)s::timestamptz
+ group by asl.tenant_member_id, asl.nickname
+),
+ranked as (
+ select *, row_number() over(partition by member_id order by weighted_hours desc) as rn
+ from x
+)
+select
+ member_id,
+ string_agg(assistant_nickname || '(' || to_char(round(weighted_hours::numeric, 1), 'FM999999990.0') || 'h)', '、' order by weighted_hours desc) as fav5
+from ranked
+where rn <= 5
+group by member_id;
+```
+
+### 评价画像:订单/时长/到店日期
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+select
+ o.member_id,
+ count(*) as orders,
+ avg(o.order_amount) as avg_order,
+ sum(o.table_use_seconds)/3600.0 as play_hours,
+ avg(o.table_use_seconds)/3600.0 as avg_play_hours,
+ min((o.order_start_time at time zone 'Asia/Shanghai')::date) as first_visit_day,
+ max((o.order_start_time at time zone 'Asia/Shanghai')::date) as last_visit_day,
+ count(distinct (o.order_start_time at time zone 'Asia/Shanghai')::date) as visit_days,
+ sum(case when o.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then 1 else 0 end) as orders_oct,
+ sum(case when o.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and o.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then 1 else 0 end) as orders_nov,
+ sum(case when o.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and o.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then 1 else 0 end) as orders_dec
+from orders o
+where o.member_id = any(%(ids)s)
+group by o.member_id;
+```
+
+### 评价画像:到店/离店时间(小时)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+, t as (
+ select
+ o.member_id,
+ extract(hour from (o.order_start_time at time zone 'Asia/Shanghai'))
+ + extract(minute from (o.order_start_time at time zone 'Asia/Shanghai'))/60.0
+ + extract(second from (o.order_start_time at time zone 'Asia/Shanghai'))/3600.0 as arrive_h,
+ extract(hour from (o.order_end_time at time zone 'Asia/Shanghai'))
+ + extract(minute from (o.order_end_time at time zone 'Asia/Shanghai'))/60.0
+ + extract(second from (o.order_end_time at time zone 'Asia/Shanghai'))/3600.0 as leave_h_raw
+ from orders o
+ where o.member_id = any(%(ids)s)
+),
+tt as (
+ select
+ member_id,
+ arrive_h,
+ case when leave_h_raw < arrive_h then leave_h_raw + 24 else leave_h_raw end as leave_h
+ from t
+)
+select
+ member_id,
+ avg(arrive_h) as arrive_avg_h,
+ percentile_cont(0.5) within group (order by arrive_h) as arrive_med_h,
+ avg(leave_h) as leave_avg_h,
+ percentile_cont(0.5) within group (order by leave_h) as leave_med_h
+from tt
+group by member_id;
+```
+
+### 评价画像:球台分区偏好(按时长)
+```sql
+select
+ tfl.member_id,
+ coalesce(tfl.site_table_area_name,'') as site_table_area_name,
+ sum(tfl.real_table_use_seconds)/3600.0 as hours
+from billiards_dwd.dwd_table_fee_log tfl
+where tfl.site_id=%(site_id)s and coalesce(tfl.is_delete,0)=0
+ and tfl.start_use_time >= %(window_start)s::timestamptz and tfl.start_use_time < %(window_end)s::timestamptz
+ and tfl.member_id = any(%(ids)s)
+group by tfl.member_id, site_table_area_name;
+```
+
+### 评价画像:商品明细(名称+数量)
+```sql
+with base_orders as (
+ select order_settle_id, max(member_id) as member_id
+ from billiards_dwd.dwd_table_fee_log
+ where site_id=%(site_id)s and coalesce(is_delete,0)=0
+ and start_use_time >= %(window_start)s::timestamptz and start_use_time < %(window_end)s::timestamptz
+ group by order_settle_id
+)
+select
+ bo.member_id,
+ g.ledger_name,
+ sum(g.ledger_count) as qty,
+ sum(g.ledger_amount) as amount
+from base_orders bo
+join billiards_dwd.dwd_store_goods_sale g on g.order_settle_id = bo.order_settle_id
+where g.site_id=%(site_id)s and coalesce(g.is_delete,0)=0
+ and bo.member_id = any(%(ids)s)
+group by bo.member_id, g.ledger_name;
+```
+
+### 评价画像:到店日期明细(用于周期/近期分析)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ max(tfl.ledger_end_time) as order_end_time,
+ sum(tfl.ledger_amount) as table_amount,
+ sum(tfl.real_table_use_seconds) as table_use_seconds
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= '2025-10-01 00:00:00+08'::timestamptz
+ and tfl.start_use_time < '2026-01-01 00:00:00+08'::timestamptz
+ group by tfl.order_settle_id
+),
+assistant_info as (
+ select
+ asl.order_settle_id,
+ sum(asl.ledger_amount) as assistant_amount,
+ min(asl.start_use_time) as assistant_start_time,
+ max(asl.last_use_time) as assistant_end_time
+ from billiards_dwd.dwd_assistant_service_log asl
+ join base_orders bo on bo.order_settle_id = asl.order_settle_id
+ where asl.site_id = %(site_id)s
+ and coalesce(asl.is_delete,0) = 0
+ group by asl.order_settle_id
+),
+goods_amount as (
+ select
+ g.order_settle_id,
+ sum(g.ledger_amount) as goods_amount
+ from billiards_dwd.dwd_store_goods_sale g
+ join base_orders bo on bo.order_settle_id = g.order_settle_id
+ where g.site_id = %(site_id)s
+ and coalesce(g.is_delete,0) = 0
+ group by g.order_settle_id
+),
+orders as (
+ select
+ bo.order_settle_id,
+ bo.member_id,
+ least(bo.order_start_time, coalesce(a.assistant_start_time, bo.order_start_time)) as order_start_time,
+ greatest(bo.order_end_time, coalesce(a.assistant_end_time, bo.order_end_time)) as order_end_time,
+ bo.table_use_seconds,
+ coalesce(bo.table_amount,0) + coalesce(a.assistant_amount,0) + coalesce(g.goods_amount,0) as order_amount
+ from base_orders bo
+ left join assistant_info a on a.order_settle_id = bo.order_settle_id
+ left join goods_amount g on g.order_settle_id = bo.order_settle_id
+)
+
+select
+ o.member_id,
+ (o.order_start_time at time zone 'Asia/Shanghai')::date as visit_date,
+ count(*) as orders,
+ sum(o.order_amount) as amount
+from orders o
+where o.member_id = any(%(ids)s)
+group by o.member_id, visit_date
+order by o.member_id, visit_date;
+```
diff --git a/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.csv b/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.csv
new file mode 100644
index 0000000..24f1db7
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.csv
@@ -0,0 +1,119 @@
+2025年10-12月 财务优惠(会员折扣+台费调账)分布
+优惠=会员折扣(dwd_table_fee_log.member_discount_amount)+台费调账(dwd_table_fee_adjust.ledger_amount),按订单归集后汇总到客户(member_id),按订单最早开台时间切月;不含团购抵扣等其它优惠。
+
+客户名称,手机号(脱敏),VIP卡/等级,10月,10月,10月,11月,11月,11月,12月,12月,12月,10-12月
+客户名称,手机号(脱敏),VIP卡/等级,会员折扣(元),台费调账(元),合计优惠(元),会员折扣(元),台费调账(元),合计优惠(元),会员折扣(元),台费调账(元),合计优惠(元),合计优惠(元)
+轩哥,188****7530,储值卡,0.00,9212.40,9212.40,0.00,10685.47,10685.47,0.00,5331.76,5331.76,25229.63
+曾巧明,186****1488,年卡,9649.06,0.00,9649.06,8811.59,0.00,8811.59,6283.51,0.00,6283.51,24744.16
+黄生,136****9719,年卡,7821.94,0.00,7821.94,6353.05,0.00,6353.05,4181.24,0.00,4181.24,18356.23
+蔡总,159****8893,台费卡,0.00,0.00,0.00,0.00,12274.20,12274.20,0.00,2587.28,2587.28,14861.48
+罗先生,139****6996,年卡,3315.05,566.48,3881.53,4474.12,460.59,4934.71,2087.14,1320.22,3407.36,12223.60
+陈腾鑫,178****8218,台费卡,0.00,2843.20,2843.20,0.00,4913.52,4913.52,0.00,1935.78,1935.78,9692.50
+谢俊,186****5198,年卡,4193.93,0.00,4193.93,4089.12,0.00,4089.12,969.66,0.00,969.66,9252.71
+桂先生,166****7275,月卡,2175.11,0.00,2175.11,4009.66,301.18,4310.84,0.00,568.24,568.24,7054.19
+张先生,139****8852,年卡,1317.04,1307.13,2624.17,2114.89,168.51,2283.40,2007.34,0.00,2007.34,6914.91
+艾宇民,150****9958,年卡,2342.73,0.00,2342.73,2543.78,545.12,3088.90,1179.56,0.00,1179.56,6611.19
+曾丹烨,139****3242,储值卡,0.00,2348.26,2348.26,0.00,2573.25,2573.25,0.00,1240.20,1240.20,6161.71
+葛先生,138****8071,储值卡,0.00,0.00,0.00,0.00,3548.54,3548.54,0.00,2593.02,2593.02,6141.56
+小燕,178****1334,储值卡,0.00,0.00,0.00,0.00,2250.36,2250.36,0.00,2228.54,2228.54,4478.90
+孟紫龙,176****3741,月卡,0.00,0.00,0.00,576.78,0.00,576.78,2762.95,0.00,2762.95,3339.73
+江先生,188****4838,储值卡,0.00,344.54,344.54,0.00,1454.41,1454.41,0.00,405.54,405.54,2204.49
+郑先生,159****4331,储值卡,0.00,0.00,0.00,0.00,1659.16,1659.16,0.00,463.02,463.02,2122.18
+黄先生,135****3507,台费卡,0.00,631.08,631.08,0.00,631.56,631.56,0.00,810.48,810.48,2073.12
+孟紫龙(该会员已注销),176****37411,月卡,1785.72,0.00,1785.72,0.00,164.00,164.00,0.00,0.00,0.00,1949.72
+T,180****9962,储值卡,0.00,578.93,578.93,0.00,461.72,461.72,0.00,839.34,839.34,1879.99
+林先生,133****1070,储值卡,0.00,0.00,0.00,0.00,199.95,199.95,0.00,1417.70,1417.70,1617.65
+游,172****6666,储值卡,0.00,0.00,0.00,0.00,921.43,921.43,0.00,600.85,600.85,1522.28
+林先生,137****8785,储值卡,0.00,0.00,0.00,0.00,1114.20,1114.20,0.00,186.45,186.45,1300.65
+桂先生(该会员已注销),166****72751,月卡,988.04,303.77,1291.81,0.00,0.00,0.00,0.00,0.00,0.00,1291.81
+叶先生,138****9539,储值卡,0.00,703.64,703.64,0.00,341.29,341.29,0.00,99.41,99.41,1144.34
+陈德韩,134****7864,台费卡,0.00,1091.02,1091.02,0.00,0.00,0.00,0.00,0.00,0.00,1091.02
+周周,198****8725,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,1061.95,1061.95,1061.95
+胡先生,186****3391,储值卡,0.00,0.00,0.00,0.00,785.20,785.20,0.00,100.59,100.59,885.79
+小熊,139****0145,台费卡,0.00,297.01,297.01,0.00,530.45,530.45,0.00,0.00,0.00,827.46
+夏,191****2851,储值卡,0.00,659.78,659.78,0.00,137.90,137.90,0.00,0.00,0.00,797.68
+李先生,186****8308,储值卡,0.00,0.00,0.00,0.00,777.27,777.27,0.00,0.00,0.00,777.27
+叶总,137****3287,储值卡,0.00,737.12,737.12,0.00,0.00,0.00,0.00,0.00,0.00,737.12
+羊,187****5094,储值卡,0.00,38.64,38.64,0.00,647.57,647.57,0.00,0.00,0.00,686.21
+黄先生,158****2109,储值卡,0.00,240.00,240.00,0.00,326.90,326.90,0.00,100.06,100.06,666.96
+卢广贤,186****6220,年卡,263.07,0.00,263.07,250.51,0.00,250.51,128.86,0.00,128.86,642.44
+陶,189****2151,储值卡,0.00,604.89,604.89,0.00,0.00,0.00,0.00,0.00,0.00,604.89
+大G,186****4598,台费卡,0.00,0.00,0.00,0.00,245.70,245.70,0.00,356.31,356.31,602.01
+明哥,166****0999,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,547.68,547.68,547.68
+梅,136****4552,储值卡,0.00,0.00,0.00,0.00,99.02,99.02,0.00,372.66,372.66,471.68
+阿亮,159****2628,储值卡,0.00,0.00,0.00,0.00,361.34,361.34,0.00,100.86,100.86,462.20
+牛先生,152****5159,台费卡,0.00,0.00,0.00,0.00,424.31,424.31,0.00,0.00,0.00,424.31
+罗超杰,137****8012,储值卡,0.00,245.95,245.95,0.00,164.54,164.54,0.00,0.00,0.00,410.49
+陈世,134****1938,储值卡,0.00,199.51,199.51,0.00,198.89,198.89,0.00,0.00,0.00,398.40
+曾先生,133****1235,储值卡,0.00,36.67,36.67,0.00,265.71,265.71,0.00,90.45,90.45,392.83
+李,131****9882,储值卡,0.00,254.13,254.13,0.00,138.12,138.12,0.00,0.00,0.00,392.25
+陈泽斌,132****6060,储值卡,0.00,77.00,77.00,0.00,222.00,222.00,0.00,78.00,78.00,377.00
+王先生,136****0168,台费卡,0.00,0.00,0.00,0.00,235.00,235.00,0.00,65.00,65.00,300.00
+林先生,188****0332,储值卡,0.00,0.00,0.00,0.00,252.11,252.11,0.00,0.00,0.00,252.11
+歌神,188****2164,储值卡,0.00,246.28,246.28,0.00,0.00,0.00,0.00,0.00,0.00,246.28
+陈先生,159****2829,台费卡,0.00,21.00,21.00,0.00,218.13,218.13,0.00,0.00,0.00,239.13
+黄先生,191****8219,台费卡,0.00,0.00,0.00,0.00,229.16,229.16,0.00,0.00,0.00,229.16
+汪先生,139****6339,储值卡,0.00,228.07,228.07,0.00,0.00,0.00,0.00,0.00,0.00,228.07
+王龙,186****8011,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,200.78,200.78,200.78
+罗先生,139****9222,储值卡,0.00,0.00,0.00,0.00,199.17,199.17,0.00,0.00,0.00,199.17
+吴生,136****3341,储值卡,0.00,0.00,0.00,0.00,99.23,99.23,0.00,99.92,99.92,199.15
+刘女士,177****7538,储值卡,0.00,193.29,193.29,0.00,0.00,0.00,0.00,0.00,0.00,193.29
+林总,138****1180,储值卡,0.00,0.00,0.00,0.00,183.25,183.25,0.00,0.00,0.00,183.25
+陈淑涛,132****5485,储值卡,0.00,0.00,0.00,0.00,180.86,180.86,0.00,0.00,0.00,180.86
+张丹逸,136****6637,储值卡,0.00,133.68,133.68,0.00,0.00,0.00,0.00,45.00,45.00,178.68
+孙启明,137****6325,台费卡,0.00,90.00,90.00,0.00,85.00,85.00,0.00,0.00,0.00,175.00
+陈先生,138****3964,储值卡,0.00,98.00,98.00,0.00,0.00,0.00,0.00,60.00,60.00,158.00
+杜先生,188****4705,台费卡,0.00,48.00,48.00,0.00,99.73,99.73,0.00,0.00,0.00,147.73
+周先生,193****6822,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,135.65,135.65,135.65
+君姐,166****4594,储值卡,0.00,0.00,0.00,0.00,134.10,134.10,0.00,0.00,0.00,134.10
+昌哥,137****1229,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,122.03,122.03,122.03
+amy,137****8221,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,116.28,116.28,116.28
+杨,130****5960,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,116.00,116.00,116.00
+方先生,153****3185,储值卡,0.00,100.27,100.27,0.00,0.00,0.00,0.00,0.00,0.00,100.27
+方先生,158****6447,台费卡,0.00,0.00,0.00,0.00,72.00,72.00,0.00,28.00,28.00,100.00
+陈先生,133****6117,台费卡,0.00,0.00,0.00,0.00,100.00,100.00,0.00,0.00,0.00,100.00
+周先生,159****9997,台费卡,0.00,0.00,0.00,0.00,61.00,61.00,0.00,37.00,37.00,98.00
+王姐,158****8819,储值卡,0.00,97.40,97.40,0.00,0.00,0.00,0.00,0.00,0.00,97.40
+老宋,138****4554,储值卡,0.00,0.00,0.00,0.00,93.95,93.95,0.00,0.00,0.00,93.95
+李先生,176****5124,储值卡,0.00,90.00,90.00,0.00,0.00,0.00,0.00,0.00,0.00,90.00
+曾先生,159****0492,储值卡,0.00,88.00,88.00,0.00,0.00,0.00,0.00,0.00,0.00,88.00
+张先生,136****4528,台费卡,0.00,0.00,0.00,0.00,37.00,37.00,0.00,45.00,45.00,82.00
+刘先生,137****2930,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,82.00,82.00,82.00
+潘先生,176****7964,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,74.00,74.00,74.00
+王先生,183****9763,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,74.00,74.00,74.00
+王先生,185****1125,台费卡,0.00,0.00,0.00,0.00,73.00,73.00,0.00,0.00,0.00,73.00
+清,130****3087,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,72.82,72.82,72.82
+贺斌,150****0885,活动抵用券,0.00,71.27,71.27,0.00,0.00,0.00,0.00,0.00,0.00,71.27
+李先生,186****9266,储值卡,0.00,0.00,0.00,0.00,69.00,69.00,0.00,0.00,0.00,69.00
+林志铭,135****4233,储值卡,0.00,0.00,0.00,0.00,66.50,66.50,0.00,0.00,0.00,66.50
+候,131****0323,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,62.79,62.79,62.79
+吕先生,155****0663,储值卡,0.00,62.54,62.54,0.00,0.00,0.00,0.00,0.00,0.00,62.54
+梁先生,134****2609,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,59.00,59.00,59.00
+肖先生,156****6427,台费卡,0.00,0.00,0.00,0.00,7.00,7.00,0.00,50.00,50.00,57.00
+婉婉,183****2742,储值卡,0.00,0.00,0.00,0.00,37.47,37.47,0.00,0.00,0.00,37.47
+陈小姐,138****0778,储值卡,0.00,32.49,32.49,0.00,0.00,0.00,0.00,0.00,0.00,32.49
+黄国磊,131****3045,台费卡,0.00,0.30,0.30,0.00,19.00,19.00,0.00,0.00,0.00,19.30
+小宇,187****8077,储值卡,0.00,13.42,13.42,0.00,0.00,0.00,0.00,0.00,0.00,13.42
+胡总,133****3091,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,1.00,1.00,1.00
+李先生,131****4000,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+周先生,173****7775,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+林先生,159****0021,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+魏先生,137****6862,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+都先生,138****7796,活动抵用券,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+陈先生,188****8626,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+冯先生,155****0348,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+常总,185****7188,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+邓飛,136****9597,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+李先生,134****4343,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+谭先生,138****3185,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+黎先生,133****0983,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+刘哥,135****0020,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+孙先生,135****3191,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+钟智豪,188****2803,活动抵用券,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+陈先生,186****8238,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+郭先生,156****5001,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+钟先生,132****3438,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+唐先生,135****0785,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+陈先生,139****0419,储值卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+潘先生,186****0511,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
+罗超,137****0990,台费卡,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00,0.00
diff --git a/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.md b/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.md
new file mode 100644
index 0000000..afba5bd
--- /dev/null
+++ b/etl_billiards/docs/table_2025-12-19/财务_优惠分布_2025年10-12月.md
@@ -0,0 +1,52 @@
+# 2025年10-12月 财务优惠(会员折扣+台费调账)分布
+## 思考过程
+用台费订单为基准关联调账表,再按客户+月份汇总,输出“谁享受了优惠”及金额分布。
+
+## 查询说明
+优惠=会员折扣(dwd_table_fee_log.member_discount_amount)+台费调账(dwd_table_fee_adjust.ledger_amount),按订单归集后汇总到客户(member_id),按订单最早开台时间切月;不含团购抵扣等其它优惠。
+
+## SQL
+
+### 优惠分布(客户+月份)
+```sql
+with base_orders as (
+ select
+ tfl.order_settle_id,
+ max(tfl.member_id) as member_id,
+ min(tfl.start_use_time) as order_start_time,
+ sum(tfl.member_discount_amount) as member_discount_amount
+ from billiards_dwd.dwd_table_fee_log tfl
+ where tfl.site_id = %(site_id)s
+ and coalesce(tfl.is_delete,0) = 0
+ and tfl.start_use_time >= %(window_start)s::timestamptz
+ and tfl.start_use_time < %(window_end)s::timestamptz
+ group by tfl.order_settle_id
+),
+adjusts as (
+ select
+ tfa.order_settle_id,
+ sum(tfa.ledger_amount) as adjust_amount
+ from billiards_dwd.dwd_table_fee_adjust tfa
+ join base_orders bo on bo.order_settle_id = tfa.order_settle_id
+ where tfa.site_id = %(site_id)s
+ and coalesce(tfa.is_delete,0) = 0
+ group by tfa.order_settle_id
+)
+, x as (
+ select
+ bo.member_id,
+ case when bo.order_start_time >= '2025-10-01 00:00:00+08'::timestamptz and bo.order_start_time < '2025-11-01 00:00:00+08'::timestamptz then '2025-10' when bo.order_start_time >= '2025-11-01 00:00:00+08'::timestamptz and bo.order_start_time < '2025-12-01 00:00:00+08'::timestamptz then '2025-11' when bo.order_start_time >= '2025-12-01 00:00:00+08'::timestamptz and bo.order_start_time < '2026-01-01 00:00:00+08'::timestamptz then '2025-12' else null end as month_key,
+ coalesce(bo.member_discount_amount,0) as member_discount_amount,
+ coalesce(a.adjust_amount,0) as adjust_amount
+ from base_orders bo
+ left join adjusts a on a.order_settle_id = bo.order_settle_id
+)
+select
+ member_id,
+ month_key,
+ sum(member_discount_amount) as member_discount_sum,
+ sum(adjust_amount) as adjust_sum
+from x
+where month_key is not null
+group by member_id, month_key;
+```
diff --git a/etl_billiards/docs/在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。.md b/etl_billiards/docs/在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。.md
new file mode 100644
index 0000000..d949212
--- /dev/null
+++ b/etl_billiards/docs/在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。.md
@@ -0,0 +1,34 @@
+在线抓取,更新ODS ,然后将更新的ODS内容,对应到DWD的更新。
+
+
+可以按“两段定时”跑:先在线抓取+入库更新 ODS,再跑 DWD_LOAD_FROM_ODS 把新增/变更同步到 DWD。CLI 用 python -m etl_billiards.cli.main。
+
+1) ODS:在线抓取 + 入库(FULL)
+python -m etl_billiards.cli.main ^
+ --pipeline-flow FULL ^
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER ^
+ --pg-dsn "%PG_DSN%" ^
+ --store-id %STORE_ID% ^
+ --api-token "%API_TOKEN%"
+(可选)指定落盘目录:加 --fetch-root "export/JSON";美化 JSON:--write-pretty-json
+
+2) DWD:ODS → DWD
+python -m etl_billiards.cli.main ^
+ --pipeline-flow INGEST_ONLY ^
+ --tasks DWD_LOAD_FROM_ODS ^
+ --pg-dsn "%PG_DSN%" ^
+ --store-id %STORE_ID%
+推荐的环境变量
+PG_DSN=postgresql://user:pwd@host:5432/db
+STORE_ID=...
+API_TOKEN=...
+(可选)JSON_FETCH_ROOT=... / FETCH_ROOT=...,LOG_ROOT=...
+如果你希望“一条命令顺序跑完 ODS+DWD”,也可以直接:
+
+python -m etl_billiards.cli.main ^
+ --pipeline-flow FULL ^
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER,DWD_LOAD_FROM_ODS ^
+ --pg-dsn "%PG_DSN%" ^
+ --store-id %STORE_ID% ^
+ --api-token "%API_TOKEN%"
+(这会对前半段任务走在线抓取+入库,对 DWD_LOAD_FROM_ODS 只做入库阶段,因为它没有抓取逻辑。)
diff --git a/etl_billiards/etl_billiards/reports/dwd_quality_report.json b/etl_billiards/etl_billiards/reports/dwd_quality_report.json
new file mode 100644
index 0000000..5d2508c
--- /dev/null
+++ b/etl_billiards/etl_billiards/reports/dwd_quality_report.json
@@ -0,0 +1,692 @@
+{
+ "generated_at": "2026-01-16T01:53:35.751172",
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 1,
+ "ods": 17217,
+ "diff": -17216
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 1,
+ "ods": 17217,
+ "diff": -17216
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "count": {
+ "dwd": 22055,
+ "ods": 22055,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "count": {
+ "dwd": 22055,
+ "ods": 22055,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 17217,
+ "ods": 17217,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 294914.58,
+ "ods_sum": 294914.58,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 896198.51,
+ "ods_sum": 896198.51,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 1961129.99,
+ "ods_sum": 1961129.99,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 186470.94,
+ "ods_sum": 186470.94,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 775239.96,
+ "ods_sum": 775239.96,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 17217,
+ "ods": 17217,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "count": {
+ "dwd": 2648,
+ "ods": 2648,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 303909.03,
+ "ods_sum": 303909.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "count": {
+ "dwd": 2648,
+ "ods": 2648,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 3116.75,
+ "ods_sum": 3116.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 373588.1,
+ "ods_sum": 373588.1,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 351914.9,
+ "ods_sum": 351914.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "count": {
+ "dwd": 466588,
+ "ods": 17563,
+ "diff": 449025
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 571932.5,
+ "ods_sum": 21673.2,
+ "diff": 550259.3
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "count": {
+ "dwd": 4252,
+ "ods": 4666,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 10489.93,
+ "ods_sum": 10879.86,
+ "diff": -389.9300000000003
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 1336399.55,
+ "ods_sum": 1459374.61,
+ "diff": -122975.06000000006
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "count": {
+ "dwd": 4666,
+ "ods": 4666,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "count": {
+ "dwd": 4492,
+ "ods": 4492,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "count": {
+ "dwd": 4492,
+ "ods": 4492,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "count": {
+ "dwd": 10544,
+ "ods": 10544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 668774.0,
+ "ods_sum": 668774.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 641028.09,
+ "ods_sum": 641028.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "count": {
+ "dwd": 10544,
+ "ods": 10544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 1040212.0,
+ "ods_sum": 1040212.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "count": {
+ "dwd": 431,
+ "ods": 431,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "count": {
+ "dwd": 431,
+ "ods": 431,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "count": {
+ "dwd": 21611,
+ "ods": 21611,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 2073449.0,
+ "ods_sum": 2073449.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -68958.0,
+ "ods_sum": -68958.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "note": "行数/金额核对,金额字段基于列名包含 amount/money/fee/balance 的数值列自动扫描。"
+}
\ No newline at end of file
diff --git a/etl_billiards/fetch-test/README.md b/etl_billiards/fetch-test/README.md
new file mode 100644
index 0000000..f438797
--- /dev/null
+++ b/etl_billiards/fetch-test/README.md
@@ -0,0 +1,25 @@
+# fetch-test
+
+用于放置“接口联调/规则验证”的一次性脚本(不影响主流程)。
+
+## 近期记录 vs 历史记录(Former) 对比
+
+脚本:`fetch-test/compare_recent_former_endpoints.py`
+
+默认对比窗口(end 为次日 00:00:00,与 ETL 窗口一致):
+- 近期:2025-12-01 ~ 2025-12-15
+- 历史:2025-08-01 ~ 2025-08-15
+
+运行:
+```bash
+cd etl_billiards
+python fetch-test/compare_recent_former_endpoints.py
+```
+
+输出:
+- `etl_billiards/fetch-test/recent_vs_former_report.md`
+- `etl_billiards/fetch-test/recent_vs_former_report.json`
+
+依赖:
+- `.env` 需配置 `API_TOKEN`(或 `FICOO_TOKEN`)与 `STORE_ID`,并保证 `API_BASE` 正确。
+
diff --git a/etl_billiards/fetch-test/compare_recent_former_endpoints.py b/etl_billiards/fetch-test/compare_recent_former_endpoints.py
new file mode 100644
index 0000000..fde2a36
--- /dev/null
+++ b/etl_billiards/fetch-test/compare_recent_former_endpoints.py
@@ -0,0 +1,434 @@
+# -*- coding: utf-8 -*-
+"""
+对比“近期记录”与“历史记录(Former)”接口:
+- 是否能正确响应(HTTP + API code==0)
+- 返回字段(基于 sample records 的 JSON path)是否一致
+
+默认时间窗口(与 ETL 窗口语义一致,end 为次日 00:00:00):
+- 近期:2025-12-01 ~ 2025-12-15(end=2025-12-16 00:00:00)
+- 历史:2025-08-01 ~ 2025-08-15(end=2025-08-16 00:00:00)
+"""
+
+from __future__ import annotations
+
+import argparse
+import json
+import sys
+from dataclasses import asdict, dataclass
+from datetime import datetime, timedelta
+from pathlib import Path
+from typing import Any, Iterable
+
+from dateutil import parser as dtparser
+from zoneinfo import ZoneInfo
+
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from api.client import APIClient
+from api.endpoint_routing import derive_former_endpoint as derive_former_endpoint_shared
+from config.settings import AppConfig
+from models.parsers import TypeParser
+from tasks.ods_json_archive_task import EndpointSpec, OdsJsonArchiveTask
+
+CHINESE_NAMES: dict[str, str] = {
+ "/MemberProfile/GetMemberCardBalanceChange": "会员余额变动",
+ "/AssistantPerformance/GetOrderAssistantDetails": "助教服务记录",
+ "/AssistantPerformance/GetAbolitionAssistant": "助教撤销/作废记录",
+ "/TenantGoods/GetGoodsSalesList": "商品销售记录",
+ "/Site/GetSiteTableUseDetails": "团购核销记录",
+ "/Site/GetSiteTableOrderDetails": "台费订单明细",
+ "/Site/GetTaiFeeAdjustList": "台费调整/优惠记录",
+ "/GoodsStockManage/QueryGoodsOutboundReceipt": "出库单/出库记录",
+ "/Promotion/GetOfflineCouponConsumePageList": "平台券核销记录",
+ "/Order/GetRefundPayLogList": "退款记录",
+ "/Site/GetAllOrderSettleList": "结账记录",
+ "/Site/GetRechargeSettleList": "充值结算记录",
+ "/PayLog/GetPayLogListPage": "支付记录",
+}
+
+
+@dataclass
+class EndpointCheckResult:
+ name_zh: str
+ recent_endpoint: str
+ recent_ok: bool
+ former_endpoint: str
+ former_ok: bool
+ has_schema_diff: str # "是" | "否" | "未知"
+ diff_detail: str
+ recent_records: int | None = None
+ former_records: int | None = None
+ recent_error: str | None = None
+ former_error: str | None = None
+ extracted_list_key: str | None = None
+
+
+def _reconfigure_stdout_utf8():
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+
+
+def derive_former_endpoint(endpoint: str) -> str | None:
+ # backward compatible wrapper: keep local name but delegate to shared router
+ return derive_former_endpoint_shared(endpoint)
+
+
+def _parse_day_start(d: str, tz: ZoneInfo) -> datetime:
+ dt = dtparser.parse(d)
+ if dt.tzinfo is None:
+ dt = dt.replace(tzinfo=tz)
+ else:
+ dt = dt.astimezone(tz)
+ return dt.replace(hour=0, minute=0, second=0, microsecond=0)
+
+
+def _window_from_dates(start_date: str, end_date_inclusive: str, tz: ZoneInfo) -> tuple[datetime, datetime]:
+ start = _parse_day_start(start_date, tz)
+ end_inclusive = _parse_day_start(end_date_inclusive, tz)
+ end_exclusive = end_inclusive + timedelta(days=1)
+ return start, end_exclusive
+
+
+def _build_window_params(
+ window_style: str,
+ store_id: int,
+ window_start: datetime,
+ window_end: datetime,
+ tz: ZoneInfo,
+) -> dict:
+ if window_style == "none":
+ return {}
+ if window_style == "site":
+ return {"siteId": store_id}
+ if window_style == "range":
+ return {
+ "siteId": store_id,
+ "rangeStartTime": TypeParser.format_timestamp(window_start, tz),
+ "rangeEndTime": TypeParser.format_timestamp(window_end, tz),
+ }
+ if window_style == "pay":
+ return {
+ "siteId": store_id,
+ "StartPayTime": TypeParser.format_timestamp(window_start, tz),
+ "EndPayTime": TypeParser.format_timestamp(window_end, tz),
+ }
+ return {
+ "siteId": store_id,
+ "startTime": TypeParser.format_timestamp(window_start, tz),
+ "endTime": TypeParser.format_timestamp(window_end, tz),
+ }
+
+
+def _extract_records(payload: dict, spec: EndpointSpec) -> tuple[list, str | None]:
+ # 优先使用 spec.list_key;若拿不到数据,再尝试自动推断(None)。
+ records_primary = APIClient._extract_list(payload, spec.data_path, spec.list_key)
+ if records_primary:
+ return records_primary, spec.list_key
+
+ records_fallback = APIClient._extract_list(payload, spec.data_path, None)
+ if records_fallback:
+ return records_fallback, None
+
+ return [], spec.list_key
+
+
+def _walk_paths(obj: Any, prefix: str, out: set[str], max_depth: int, depth: int, sample_list_elems: int):
+ if depth > max_depth:
+ return
+ if isinstance(obj, dict):
+ for k, v in obj.items():
+ if not isinstance(k, str):
+ k = str(k)
+ p = f"{prefix}.{k}" if prefix else k
+ out.add(p)
+ _walk_paths(v, p, out, max_depth, depth + 1, sample_list_elems)
+ elif isinstance(obj, list):
+ p = f"{prefix}[]" if prefix else "[]"
+ out.add(p)
+ for v in obj[:sample_list_elems]:
+ _walk_paths(v, p, out, max_depth, depth + 1, sample_list_elems)
+
+
+def _schema_from_records(records: list, max_records: int, max_depth: int) -> set[str]:
+ paths: set[str] = set()
+ for rec in (records or [])[:max_records]:
+ _walk_paths(rec, "", paths, max_depth=max_depth, depth=0, sample_list_elems=5)
+ return paths
+
+
+def _schema_from_data(payload: dict, data_path: tuple[str, ...], max_depth: int) -> set[str]:
+ cur: Any = payload
+ for k in data_path:
+ if isinstance(cur, dict):
+ cur = cur.get(k)
+ else:
+ cur = None
+ if cur is None:
+ break
+ paths: set[str] = set()
+ _walk_paths(cur, "", paths, max_depth=max_depth, depth=0, sample_list_elems=5)
+ return paths
+
+
+def _cell(text: str) -> str:
+ # markdown table cell escape
+ s = (text or "").replace("|", "\\|").replace("\n", "
")
+ return s
+
+
+def _format_diff(recent_paths: set[str], former_paths: set[str], limit: int = 60) -> tuple[str, str]:
+ if recent_paths == former_paths:
+ return "否", ""
+
+ only_recent = sorted(recent_paths - former_paths)
+ only_former = sorted(former_paths - recent_paths)
+
+ parts: list[str] = []
+ if only_recent:
+ truncated = only_recent[:limit]
+ suffix = "" if len(only_recent) <= limit else f" ...(+{len(only_recent) - limit})"
+ parts.append(f"仅近期({len(only_recent)}): " + ", ".join(truncated) + suffix)
+ if only_former:
+ truncated = only_former[:limit]
+ suffix = "" if len(only_former) <= limit else f" ...(+{len(only_former) - limit})"
+ parts.append(f"仅历史({len(only_former)}): " + ", ".join(truncated) + suffix)
+
+ return "是", "\n".join(parts).strip()
+
+
+def _post_first_page(
+ client: APIClient,
+ endpoint: str,
+ params: dict,
+ page_size: int,
+ spec: EndpointSpec,
+) -> tuple[dict, list]:
+ # 只拉取第 1 页,用于“能否响应”与字段对比
+ payload: dict | None = None
+ records: list = []
+ for _, page_records, _, raw in client.iter_paginated(
+ endpoint=endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=spec.data_path,
+ list_key=spec.list_key,
+ page_end=1,
+ ):
+ payload = raw
+ records = page_records or []
+ break
+ return (payload or {}), (records or [])
+
+
+def _load_specs_for_range_only() -> list[EndpointSpec]:
+ # 以 ODS_JSON_ARCHIVE 的 ENDPOINTS 为准,筛选出“可定义时间范围”的接口
+ specs: list[EndpointSpec] = []
+ for spec in OdsJsonArchiveTask.ENDPOINTS:
+ if spec.window_style in ("start_end", "range", "pay"):
+ specs.append(spec)
+ return specs
+
+
+def main() -> int:
+ _reconfigure_stdout_utf8()
+ ap = argparse.ArgumentParser()
+ ap.add_argument("--recent-start", default="2025-12-01")
+ ap.add_argument("--recent-end", default="2025-12-15")
+ ap.add_argument("--former-start", default="2025-08-01")
+ ap.add_argument("--former-end", default="2025-08-15")
+ ap.add_argument("--page-size", type=int, default=50)
+ ap.add_argument("--max-records", type=int, default=50)
+ ap.add_argument("--max-depth", type=int, default=5)
+ ap.add_argument(
+ "--out",
+ default=str(Path(__file__).with_name("recent_vs_former_report.md")),
+ help="输出 markdown 路径",
+ )
+ ap.add_argument(
+ "--out-json",
+ default=str(Path(__file__).with_name("recent_vs_former_report.json")),
+ help="输出 json 路径(含错误信息与统计)",
+ )
+ args = ap.parse_args()
+
+ cfg = AppConfig.load().config
+ tz = ZoneInfo(cfg["app"]["timezone"])
+ store_id = int(cfg["app"]["store_id"])
+
+ recent_start, recent_end = _window_from_dates(args.recent_start, args.recent_end, tz)
+ former_start, former_end = _window_from_dates(args.former_start, args.former_end, tz)
+
+ if not cfg["api"].get("token"):
+ raise SystemExit("缺少 api.token(请在 .env 配置 API_TOKEN 或 FICOO_TOKEN)")
+
+ client = APIClient(
+ base_url=cfg["api"]["base_url"],
+ token=cfg["api"]["token"],
+ timeout=int(cfg["api"].get("timeout_sec") or 20),
+ retry_max=int(cfg["api"].get("retries", {}).get("max_attempts") or 3),
+ headers_extra=cfg["api"].get("headers_extra") or {},
+ )
+
+ common_params = cfg["api"].get("params", {}) or {}
+ if not isinstance(common_params, dict):
+ common_params = {}
+
+ results: list[EndpointCheckResult] = []
+ specs = _load_specs_for_range_only()
+
+ for spec in specs:
+ name_zh = CHINESE_NAMES.get(spec.endpoint) or Path(spec.endpoint).name
+ former_endpoint = derive_former_endpoint(spec.endpoint)
+
+ # recent
+ recent_params = dict(common_params)
+ recent_params.update(_build_window_params(spec.window_style, store_id, recent_start, recent_end, tz))
+
+ recent_ok = False
+ recent_records: list = []
+ recent_payload: dict = {}
+ recent_err: str | None = None
+
+ try:
+ recent_payload, recent_records = _post_first_page(
+ client=client,
+ endpoint=spec.endpoint,
+ params=recent_params,
+ page_size=args.page_size,
+ spec=spec,
+ )
+ recent_ok = True
+ except Exception as e:
+ recent_err = f"{type(e).__name__}: {e}"
+
+ # former
+ former_params = dict(common_params)
+ former_params.update(_build_window_params(spec.window_style, store_id, former_start, former_end, tz))
+
+ former_ok = False
+ former_records: list = []
+ former_payload: dict = {}
+ former_err: str | None = None
+
+ if not former_endpoint:
+ former_err = "未提供历史记录接口 path"
+ else:
+ try:
+ former_payload, former_records = _post_first_page(
+ client=client,
+ endpoint=former_endpoint,
+ params=former_params,
+ page_size=args.page_size,
+ spec=spec,
+ )
+ former_ok = True
+ except Exception as e:
+ former_err = f"{type(e).__name__}: {e}"
+
+ extracted_key: str | None = spec.list_key
+ if recent_ok and former_ok:
+ # 用“更能提取出 records 的方式”来做字段对比
+ recent_extracted, recent_key_used = _extract_records(recent_payload, spec)
+ former_extracted, former_key_used = _extract_records(former_payload, spec)
+ extracted_key = recent_key_used or former_key_used or spec.list_key
+
+ if recent_extracted and former_extracted:
+ recent_schema = _schema_from_records(recent_extracted, args.max_records, args.max_depth)
+ former_schema = _schema_from_records(former_extracted, args.max_records, args.max_depth)
+ has_diff, detail = _format_diff(recent_schema, former_schema)
+ elif (not recent_extracted) and (not former_extracted):
+ has_diff, detail = "未知", "两侧 records 均为空,无法判断字段差异"
+ else:
+ has_diff, detail = (
+ "未知",
+ f"一侧 records 为空(近期={len(recent_extracted)} 历史={len(former_extracted)}),无法判断字段差异",
+ )
+ else:
+ if former_endpoint is None:
+ has_diff, detail = "未知", "无历史记录接口,跳过字段对比"
+ else:
+ has_diff, detail = "未知", "请求失败,无法对比字段"
+
+ results.append(
+ EndpointCheckResult(
+ name_zh=name_zh,
+ recent_endpoint=spec.endpoint,
+ recent_ok=recent_ok,
+ former_endpoint=former_endpoint or "无",
+ former_ok=former_ok,
+ has_schema_diff=has_diff,
+ diff_detail=detail,
+ recent_records=len(recent_records) if recent_ok else None,
+ former_records=len(former_records) if former_ok else None,
+ recent_error=recent_err,
+ former_error=former_err,
+ extracted_list_key=extracted_key,
+ )
+ )
+
+ # markdown report
+ out_md = Path(args.out)
+ out_json = Path(args.out_json)
+ out_md.parent.mkdir(parents=True, exist_ok=True)
+
+ header = [
+ "# 近期记录 vs 历史记录(Former) 接口对比报告",
+ "",
+ f"- 近期窗口: `{recent_start.isoformat()}` ~ `{recent_end.isoformat()}`(end 为次日 00:00:00)",
+ f"- 历史窗口: `{former_start.isoformat()}` ~ `{former_end.isoformat()}`(end 为次日 00:00:00)",
+ f"- store_id: `{store_id}`",
+ f"- base_url: `{cfg['api']['base_url']}`",
+ "",
+ "表头:接口名称(中文);近期记录接口 path;近期记录是否返回;历史记录接口 path;历史记录是否返回;是否存在返回字段差异;差异字段详情。",
+ "",
+ "| 接口名称(中文) | 近期记录接口 path | 近期记录是否返回 | 历史记录接口 path | 历史记录是否返回 | 是否存在返回字段差异 | 差异字段详情 |",
+ "| --- | --- | --- | --- | --- | --- | --- |",
+ ]
+
+ rows: list[str] = []
+ for r in results:
+ rows.append(
+ "| "
+ + " | ".join(
+ [
+ _cell(r.name_zh),
+ _cell(r.recent_endpoint),
+ "是" if r.recent_ok else "否",
+ _cell(r.former_endpoint),
+ "是" if r.former_ok else "否",
+ _cell(r.has_schema_diff),
+ _cell(r.diff_detail or ""),
+ ]
+ )
+ + " |"
+ )
+
+ out_md.write_text("\n".join(header + rows) + "\n", encoding="utf-8")
+
+ out_json.write_text(
+ json.dumps(
+ {
+ "recent_window": {"start": recent_start.isoformat(), "end": recent_end.isoformat()},
+ "former_window": {"start": former_start.isoformat(), "end": former_end.isoformat()},
+ "store_id": store_id,
+ "base_url": cfg["api"]["base_url"],
+ "results": [asdict(r) for r in results],
+ },
+ ensure_ascii=False,
+ indent=2,
+ )
+ + "\n",
+ encoding="utf-8",
+ )
+
+ print(f"OK: wrote {out_md}")
+ print(f"OK: wrote {out_json}")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/fetch-test/recent_vs_former_report.json b/etl_billiards/fetch-test/recent_vs_former_report.json
new file mode 100644
index 0000000..2ce5c04
--- /dev/null
+++ b/etl_billiards/fetch-test/recent_vs_former_report.json
@@ -0,0 +1,196 @@
+{
+ "recent_window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2025-12-16T00:00:00+08:00"
+ },
+ "former_window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-08-16T00:00:00+08:00"
+ },
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "name_zh": "会员余额变动",
+ "recent_endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "recent_ok": true,
+ "former_endpoint": "/MemberProfile/GetFormerMemberCardBalanceChange",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": null
+ },
+ {
+ "name_zh": "助教服务记录",
+ "recent_endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "recent_ok": true,
+ "former_endpoint": "/AssistantPerformance/GetFormerOrderAssistantDetails",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "orderAssistantDetails"
+ },
+ {
+ "name_zh": "助教撤销/作废记录",
+ "recent_endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "recent_ok": true,
+ "former_endpoint": "无",
+ "former_ok": false,
+ "has_schema_diff": "未知",
+ "diff_detail": "无历史记录接口,跳过字段对比",
+ "recent_records": 18,
+ "former_records": null,
+ "recent_error": null,
+ "former_error": "未提供历史记录接口 path",
+ "extracted_list_key": "abolitionAssistants"
+ },
+ {
+ "name_zh": "商品销售记录",
+ "recent_endpoint": "/TenantGoods/GetGoodsSalesList",
+ "recent_ok": true,
+ "former_endpoint": "/TenantGoods/GetFormerGoodsSalesList",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "orderGoodsLedgers"
+ },
+ {
+ "name_zh": "团购核销记录",
+ "recent_endpoint": "/Site/GetSiteTableUseDetails",
+ "recent_ok": true,
+ "former_endpoint": "/Site/GetSiteTableUseDetails",
+ "former_ok": true,
+ "has_schema_diff": "未知",
+ "diff_detail": "一侧 records 为空(近期=50 历史=0),无法判断字段差异",
+ "recent_records": 50,
+ "former_records": 0,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "siteTableUseDetailsList"
+ },
+ {
+ "name_zh": "台费订单明细",
+ "recent_endpoint": "/Site/GetSiteTableOrderDetails",
+ "recent_ok": true,
+ "former_endpoint": "/Site/GetFormerSiteTableOrderDetails",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "siteTableUseDetailsList"
+ },
+ {
+ "name_zh": "台费调整/优惠记录",
+ "recent_endpoint": "/Site/GetTaiFeeAdjustList",
+ "recent_ok": true,
+ "former_endpoint": "/Site/GetFormerTaiFeeAdjustList",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "taiFeeAdjustInfos"
+ },
+ {
+ "name_zh": "出库单/出库记录",
+ "recent_endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "recent_ok": true,
+ "former_endpoint": "/GoodsStockManage/QueryFormerGoodsOutboundReceipt",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "queryDeliveryRecordsList"
+ },
+ {
+ "name_zh": "平台券核销记录",
+ "recent_endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "recent_ok": true,
+ "former_endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": null
+ },
+ {
+ "name_zh": "退款记录",
+ "recent_endpoint": "/Order/GetRefundPayLogList",
+ "recent_ok": true,
+ "former_endpoint": "无",
+ "former_ok": false,
+ "has_schema_diff": "未知",
+ "diff_detail": "无历史记录接口,跳过字段对比",
+ "recent_records": 5,
+ "former_records": null,
+ "recent_error": null,
+ "former_error": "未提供历史记录接口 path",
+ "extracted_list_key": null
+ },
+ {
+ "name_zh": "结账记录",
+ "recent_endpoint": "/Site/GetAllOrderSettleList",
+ "recent_ok": true,
+ "former_endpoint": "/Site/GetFormerOrderSettleList",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "settleList"
+ },
+ {
+ "name_zh": "充值结算记录",
+ "recent_endpoint": "/Site/GetRechargeSettleList",
+ "recent_ok": true,
+ "former_endpoint": "/Site/GetFormerRechargeSettleList",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 39,
+ "former_records": 47,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": "settleList"
+ },
+ {
+ "name_zh": "支付记录",
+ "recent_endpoint": "/PayLog/GetPayLogListPage",
+ "recent_ok": true,
+ "former_endpoint": "/PayLog/GetFormerPayLogListPage",
+ "former_ok": true,
+ "has_schema_diff": "否",
+ "diff_detail": "",
+ "recent_records": 50,
+ "former_records": 50,
+ "recent_error": null,
+ "former_error": null,
+ "extracted_list_key": null
+ }
+ ]
+}
diff --git a/etl_billiards/fetch-test/recent_vs_former_report.md b/etl_billiards/fetch-test/recent_vs_former_report.md
new file mode 100644
index 0000000..f18ce8c
--- /dev/null
+++ b/etl_billiards/fetch-test/recent_vs_former_report.md
@@ -0,0 +1,24 @@
+# 近期记录 vs 历史记录(Former) 接口对比报告
+
+- 近期窗口: `2025-12-01T00:00:00+08:00` ~ `2025-12-16T00:00:00+08:00`(end 为次日 00:00:00)
+- 历史窗口: `2025-08-01T00:00:00+08:00` ~ `2025-08-16T00:00:00+08:00`(end 为次日 00:00:00)
+- store_id: `2790685415443269`
+- base_url: `https://pc.ficoo.vip/apiprod/admin/v1/`
+
+表头:接口名称(中文);近期记录接口 path;近期记录是否返回;历史记录接口 path;历史记录是否返回;是否存在返回字段差异;差异字段详情。
+
+| 接口名称(中文) | 近期记录接口 path | 近期记录是否返回 | 历史记录接口 path | 历史记录是否返回 | 是否存在返回字段差异 | 差异字段详情 |
+| --- | --- | --- | --- | --- | --- | --- |
+| 会员余额变动 | /MemberProfile/GetMemberCardBalanceChange | 是 | /MemberProfile/GetFormerMemberCardBalanceChange | 是 | 否 | |
+| 助教服务记录 | /AssistantPerformance/GetOrderAssistantDetails | 是 | /AssistantPerformance/GetFormerOrderAssistantDetails | 是 | 否 | |
+| 助教撤销/作废记录 | /AssistantPerformance/GetAbolitionAssistant | 是 | 无 | 否 | 未知 | 无历史记录接口,跳过字段对比 |
+| 商品销售记录 | /TenantGoods/GetGoodsSalesList | 是 | /TenantGoods/GetFormerGoodsSalesList | 是 | 否 | |
+| 团购核销记录 | /Site/GetSiteTableUseDetails | 是 | /Site/GetSiteTableUseDetails | 是 | 未知 | 一侧 records 为空(近期=50 历史=0),无法判断字段差异 |
+| 台费订单明细 | /Site/GetSiteTableOrderDetails | 是 | /Site/GetFormerSiteTableOrderDetails | 是 | 否 | |
+| 台费调整/优惠记录 | /Site/GetTaiFeeAdjustList | 是 | /Site/GetFormerTaiFeeAdjustList | 是 | 否 | |
+| 出库单/出库记录 | /GoodsStockManage/QueryGoodsOutboundReceipt | 是 | /GoodsStockManage/QueryFormerGoodsOutboundReceipt | 是 | 否 | |
+| 平台券核销记录 | /Promotion/GetOfflineCouponConsumePageList | 是 | /Promotion/GetOfflineCouponConsumePageList | 是 | 否 | |
+| 退款记录 | /Order/GetRefundPayLogList | 是 | 无 | 否 | 未知 | 无历史记录接口,跳过字段对比 |
+| 结账记录 | /Site/GetAllOrderSettleList | 是 | /Site/GetFormerOrderSettleList | 是 | 否 | |
+| 充值结算记录 | /Site/GetRechargeSettleList | 是 | /Site/GetFormerRechargeSettleList | 是 | 否 | |
+| 支付记录 | /PayLog/GetPayLogListPage | 是 | /PayLog/GetFormerPayLogListPage | 是 | 否 | |
diff --git a/etl_billiards/gui/README.md b/etl_billiards/gui/README.md
new file mode 100644
index 0000000..78b3fd7
--- /dev/null
+++ b/etl_billiards/gui/README.md
@@ -0,0 +1,141 @@
+# 飞球 ETL GUI 管理系统
+
+一个基于 PySide6 的图形化 ETL 管理工具。
+
+## 功能特性
+
+- **任务配置**: 选择和配置 ETL 任务,支持参数设置和 CLI 命令预览
+- **任务管理**: 任务队列管理、执行历史记录、自动执行
+- **环境配置**: 图形化编辑 `.env` 配置文件
+- **数据库查看**: 浏览表结构、执行 SQL 查询
+- **ETL 状态**: 实时查看 ODS/DWD 数据状态和执行记录
+- **日志查看**: 实时日志输出、过滤、导出
+
+## 快速开始
+
+### 1. 安装依赖
+
+```bash
+cd etl_billiards
+pip install -r requirements.txt
+```
+
+### 2. 运行 GUI
+
+**方法一:使用启动脚本**
+
+```bash
+# Windows 命令行
+run_gui.bat
+
+# 或 PowerShell
+.\run_gui.ps1
+```
+
+**方法二:直接运行 Python**
+
+```bash
+cd etl_billiards
+python -m gui.main
+```
+
+## 打包为 EXE
+
+### 安装打包工具
+
+```bash
+pip install pyinstaller
+```
+
+### 执行打包
+
+```bash
+# 目录模式(推荐,启动更快)
+python build_exe.py
+
+# 单文件模式
+python build_exe.py --onefile
+
+# 显示控制台(调试用)
+python build_exe.py --console
+
+# 清理并重新打包
+python build_exe.py --clean
+```
+
+打包完成后,EXE 文件位于 `dist/ETL管理系统/` 目录。
+
+## 目录结构
+
+```
+gui/
+├── main.py # 应用入口
+├── main_window.py # 主窗口
+├── widgets/ # UI 组件
+│ ├── task_panel.py # 任务配置面板
+│ ├── task_manager.py # 任务管理器
+│ ├── env_editor.py # 环境变量编辑器
+│ ├── log_viewer.py # 日志查看器
+│ ├── db_viewer.py # 数据库查看器
+│ └── status_panel.py # ETL 状态面板
+├── workers/ # 后台工作线程
+│ ├── task_worker.py # 任务执行线程
+│ └── db_worker.py # 数据库查询线程
+├── models/ # 数据模型
+│ └── task_model.py # 任务数据模型
+├── utils/ # 工具模块
+│ ├── cli_builder.py # CLI 命令构建器
+│ └── config_helper.py # 配置辅助
+└── resources/ # 资源文件
+ └── styles.qss # 样式表
+```
+
+## 使用说明
+
+### 任务配置
+
+1. 在左侧选择任务分类
+2. 勾选要执行的任务
+3. 配置运行参数(Pipeline 模式、时间窗口等)
+4. 查看底部的 CLI 命令预览
+5. 点击「立即执行」或「添加到队列」
+
+### 环境配置
+
+1. 打开「环境配置」面板
+2. 编辑各项配置(数据库、API、路径等)
+3. 点击「保存」
+
+### 数据库查看
+
+1. 打开「数据库」面板
+2. 输入或使用 .env 中的 DSN
+3. 点击「连接」
+4. 浏览表结构或执行 SQL 查询
+
+## 常见问题
+
+### Q: 启动时提示缺少 PySide6
+
+```bash
+pip install PySide6
+```
+
+### Q: 连接数据库失败
+
+检查 `.env` 中的 `PG_DSN` 配置是否正确。
+
+### Q: 打包后运行闪退
+
+使用 `--console` 参数重新打包,查看错误信息:
+
+```bash
+python build_exe.py --console
+```
+
+## 技术栈
+
+- Python 3.10+
+- PySide6 (Qt for Python)
+- psycopg2 (PostgreSQL)
+- PyInstaller (打包)
diff --git a/etl_billiards/gui/__init__.py b/etl_billiards/gui/__init__.py
new file mode 100644
index 0000000..25afec8
--- /dev/null
+++ b/etl_billiards/gui/__init__.py
@@ -0,0 +1,5 @@
+# -*- coding: utf-8 -*-
+"""ETL GUI 客户端模块"""
+
+__version__ = "1.0.0"
+__author__ = "ETL Team"
diff --git a/etl_billiards/gui/main.py b/etl_billiards/gui/main.py
new file mode 100644
index 0000000..d414768
--- /dev/null
+++ b/etl_billiards/gui/main.py
@@ -0,0 +1,46 @@
+# -*- coding: utf-8 -*-
+"""ETL GUI 应用入口"""
+
+import sys
+import os
+from pathlib import Path
+
+# 确保项目根目录在 Python 路径中
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from PySide6.QtWidgets import QApplication
+from PySide6.QtCore import Qt
+from PySide6.QtGui import QFont
+
+from gui.main_window import MainWindow
+
+
+def main():
+ """主函数"""
+ # 设置高 DPI 支持
+ QApplication.setHighDpiScaleFactorRoundingPolicy(
+ Qt.HighDpiScaleFactorRoundingPolicy.PassThrough
+ )
+
+ # 创建应用
+ app = QApplication(sys.argv)
+ app.setApplicationName("飞球 ETL 管理系统")
+ app.setApplicationVersion("1.0.0")
+ app.setOrganizationName("Billiards")
+
+ # 设置默认字体
+ font = QFont("Microsoft YaHei", 10)
+ app.setFont(font)
+
+ # 创建主窗口
+ window = MainWindow()
+ window.show()
+
+ # 运行应用
+ sys.exit(app.exec())
+
+
+if __name__ == "__main__":
+ main()
diff --git a/etl_billiards/gui/main_window.py b/etl_billiards/gui/main_window.py
new file mode 100644
index 0000000..c1ff360
--- /dev/null
+++ b/etl_billiards/gui/main_window.py
@@ -0,0 +1,397 @@
+# -*- coding: utf-8 -*-
+"""主窗口"""
+
+from PySide6.QtWidgets import (
+ QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
+ QStackedWidget, QListWidget, QListWidgetItem,
+ QStatusBar, QLabel, QMessageBox, QSplitter
+)
+from PySide6.QtCore import Qt, QSize, Signal
+from PySide6.QtGui import QIcon, QAction
+
+from .widgets.task_panel import TaskPanel
+from .widgets.task_manager import TaskManager
+from .widgets.env_editor import EnvEditor
+from .widgets.log_viewer import LogViewer
+from .widgets.db_viewer import DBViewer
+from .widgets.status_panel import StatusPanel
+from .resources import load_stylesheet
+
+
+class MainWindow(QMainWindow):
+ """ETL GUI 主窗口"""
+
+ # 信号
+ status_message = Signal(str, int) # message, timeout_ms
+
+ def __init__(self):
+ super().__init__()
+ self.setWindowTitle("飞球 ETL 管理系统")
+ self.setMinimumSize(1200, 800)
+ self.resize(1400, 900)
+
+ # 应用样式
+ self.setStyleSheet(load_stylesheet())
+
+ # 初始化 UI
+ self._init_ui()
+ self._init_menu()
+ self._init_status_bar()
+ self._connect_signals()
+
+ # 默认选中第一项
+ self.nav_list.setCurrentRow(0)
+
+ # 首次显示标记
+ self._first_show = True
+
+ def showEvent(self, event):
+ """窗口显示事件"""
+ super().showEvent(event)
+ if self._first_show:
+ self._first_show = False
+ # 延迟检查配置,让窗口先显示
+ from PySide6.QtCore import QTimer
+ QTimer.singleShot(100, self._check_config_on_startup)
+
+ def _init_ui(self):
+ """初始化界面"""
+ # 中央部件
+ central_widget = QWidget()
+ self.setCentralWidget(central_widget)
+
+ # 主布局
+ main_layout = QHBoxLayout(central_widget)
+ main_layout.setContentsMargins(0, 0, 0, 0)
+ main_layout.setSpacing(0)
+
+ # 创建分割器
+ splitter = QSplitter(Qt.Horizontal)
+ main_layout.addWidget(splitter)
+
+ # 左侧导航栏
+ nav_widget = self._create_nav_widget()
+ splitter.addWidget(nav_widget)
+
+ # 右侧内容区
+ self.content_stack = QStackedWidget()
+ splitter.addWidget(self.content_stack)
+
+ # 设置分割比例
+ splitter.setSizes([200, 1200])
+ splitter.setStretchFactor(0, 0)
+ splitter.setStretchFactor(1, 1)
+
+ # 创建各个面板
+ self._create_panels()
+
+ def _create_nav_widget(self) -> QWidget:
+ """创建导航侧边栏"""
+ nav_widget = QWidget()
+ nav_widget.setMaximumWidth(220)
+ nav_widget.setMinimumWidth(180)
+
+ layout = QVBoxLayout(nav_widget)
+ layout.setContentsMargins(0, 0, 0, 0)
+ layout.setSpacing(0)
+
+ # 标题
+ title_label = QLabel(" ETL 控制台")
+ title_label.setProperty("heading", True)
+ title_label.setFixedHeight(60)
+ title_label.setAlignment(Qt.AlignVCenter)
+ layout.addWidget(title_label)
+
+ # 导航列表
+ self.nav_list = QListWidget()
+ self.nav_list.setObjectName("navList")
+ layout.addWidget(self.nav_list)
+
+ # 添加导航项
+ nav_items = [
+ ("任务配置", "配置并执行 ETL 任务"),
+ ("任务管理", "管理任务队列和历史记录"),
+ ("环境配置", "编辑 .env 配置文件"),
+ ("数据库", "查看数据库和执行查询"),
+ ("ETL 状态", "查看 ETL 运行状态"),
+ ("日志", "查看执行日志"),
+ ]
+
+ for name, tooltip in nav_items:
+ item = QListWidgetItem(name)
+ item.setToolTip(tooltip)
+ item.setSizeHint(QSize(0, 44))
+ self.nav_list.addItem(item)
+
+ return nav_widget
+
+ def _create_panels(self):
+ """创建各个功能面板"""
+ # 任务配置面板
+ self.task_panel = TaskPanel()
+ self.content_stack.addWidget(self.task_panel)
+
+ # 任务管理面板
+ self.task_manager = TaskManager()
+ self.content_stack.addWidget(self.task_manager)
+
+ # 环境配置面板
+ self.env_editor = EnvEditor()
+ self.content_stack.addWidget(self.env_editor)
+
+ # 数据库查看器
+ self.db_viewer = DBViewer()
+ self.content_stack.addWidget(self.db_viewer)
+
+ # ETL 状态面板
+ self.status_panel = StatusPanel()
+ self.content_stack.addWidget(self.status_panel)
+
+ # 日志面板
+ self.log_viewer = LogViewer()
+ self.content_stack.addWidget(self.log_viewer)
+
+ def _init_menu(self):
+ """初始化菜单栏"""
+ menubar = self.menuBar()
+
+ # 文件菜单
+ file_menu = menubar.addMenu("文件(&F)")
+
+ refresh_action = QAction("刷新配置(&R)", self)
+ refresh_action.setShortcut("Ctrl+R")
+ refresh_action.triggered.connect(self._refresh_config)
+ file_menu.addAction(refresh_action)
+
+ settings_action = QAction("设置(&S)...", self)
+ settings_action.setShortcut("Ctrl+,")
+ settings_action.triggered.connect(self._show_settings)
+ file_menu.addAction(settings_action)
+
+ file_menu.addSeparator()
+
+ exit_action = QAction("退出(&X)", self)
+ exit_action.setShortcut("Ctrl+Q")
+ exit_action.triggered.connect(self.close)
+ file_menu.addAction(exit_action)
+
+ # 视图菜单
+ view_menu = menubar.addMenu("视图(&V)")
+
+ task_config_action = QAction("任务配置(&T)", self)
+ task_config_action.setShortcut("Ctrl+1")
+ task_config_action.triggered.connect(lambda: self._switch_panel(0))
+ view_menu.addAction(task_config_action)
+
+ task_manager_action = QAction("任务管理(&M)", self)
+ task_manager_action.setShortcut("Ctrl+2")
+ task_manager_action.triggered.connect(lambda: self._switch_panel(1))
+ view_menu.addAction(task_manager_action)
+
+ env_action = QAction("环境配置(&E)", self)
+ env_action.setShortcut("Ctrl+3")
+ env_action.triggered.connect(lambda: self._switch_panel(2))
+ view_menu.addAction(env_action)
+
+ db_action = QAction("数据库(&D)", self)
+ db_action.setShortcut("Ctrl+4")
+ db_action.triggered.connect(lambda: self._switch_panel(3))
+ view_menu.addAction(db_action)
+
+ status_action = QAction("ETL 状态(&S)", self)
+ status_action.setShortcut("Ctrl+5")
+ status_action.triggered.connect(lambda: self._switch_panel(4))
+ view_menu.addAction(status_action)
+
+ log_action = QAction("日志(&L)", self)
+ log_action.setShortcut("Ctrl+6")
+ log_action.triggered.connect(lambda: self._switch_panel(5))
+ view_menu.addAction(log_action)
+
+ # 帮助菜单
+ help_menu = menubar.addMenu("帮助(&H)")
+
+ about_action = QAction("关于(&A)", self)
+ about_action.triggered.connect(self._show_about)
+ help_menu.addAction(about_action)
+
+ def _init_status_bar(self):
+ """初始化状态栏"""
+ self.status_bar = QStatusBar()
+ self.setStatusBar(self.status_bar)
+
+ # 连接状态
+ self.conn_status_label = QLabel("数据库: 未连接")
+ self.conn_status_label.setProperty("status", "warning")
+ self.status_bar.addPermanentWidget(self.conn_status_label)
+
+ # 任务状态
+ self.task_status_label = QLabel("任务: 空闲")
+ self.status_bar.addPermanentWidget(self.task_status_label)
+
+ # 默认消息
+ self.status_bar.showMessage("就绪", 3000)
+
+ def _connect_signals(self):
+ """连接信号"""
+ # 导航切换
+ self.nav_list.currentRowChanged.connect(self._on_nav_changed)
+
+ # 任务面板信号
+ self.task_panel.task_started.connect(self._on_task_started)
+ self.task_panel.task_finished.connect(self._on_task_finished)
+ self.task_panel.log_message.connect(self.log_viewer.append_log)
+ self.task_panel.add_to_queue.connect(self._on_add_to_queue)
+ self.task_panel.create_schedule.connect(self._on_create_schedule)
+
+ # 任务管理器信号
+ self.task_manager.task_started.connect(self._on_task_started)
+ self.task_manager.task_finished.connect(self._on_task_finished)
+ self.task_manager.log_message.connect(self.log_viewer.append_log)
+
+ # 数据库连接状态
+ self.db_viewer.connection_changed.connect(self._on_db_connection_changed)
+
+ # 状态消息
+ self.status_message.connect(self._show_status_message)
+
+ def _on_nav_changed(self, index: int):
+ """导航项切换"""
+ self.content_stack.setCurrentIndex(index)
+
+ def _switch_panel(self, index: int):
+ """切换到指定面板"""
+ self.nav_list.setCurrentRow(index)
+
+ def _refresh_config(self):
+ """刷新配置"""
+ self.env_editor.load_config()
+ self.task_panel.refresh_tasks()
+ self.status_bar.showMessage("配置已刷新", 3000)
+
+ def _on_task_started(self, task_info: str):
+ """任务开始时"""
+ self.task_status_label.setText(f"任务: 执行中 - {task_info}")
+ self.task_status_label.setProperty("status", "info")
+ self.task_status_label.style().unpolish(self.task_status_label)
+ self.task_status_label.style().polish(self.task_status_label)
+
+ def _on_task_finished(self, success: bool, message: str):
+ """任务完成时"""
+ if success:
+ self.task_status_label.setText("任务: 完成")
+ self.task_status_label.setProperty("status", "success")
+ else:
+ self.task_status_label.setText("任务: 失败")
+ self.task_status_label.setProperty("status", "error")
+ self.task_status_label.style().unpolish(self.task_status_label)
+ self.task_status_label.style().polish(self.task_status_label)
+ self.status_bar.showMessage(message, 5000)
+
+ def _on_db_connection_changed(self, connected: bool, message: str):
+ """数据库连接状态变化"""
+ if connected:
+ self.conn_status_label.setText("数据库: 已连接")
+ self.conn_status_label.setProperty("status", "success")
+ else:
+ self.conn_status_label.setText("数据库: 未连接")
+ self.conn_status_label.setProperty("status", "warning")
+ self.conn_status_label.style().unpolish(self.conn_status_label)
+ self.conn_status_label.style().polish(self.conn_status_label)
+ if message:
+ self.status_bar.showMessage(message, 3000)
+
+ def _show_status_message(self, message: str, timeout: int):
+ """显示状态栏消息"""
+ self.status_bar.showMessage(message, timeout)
+
+ def _on_add_to_queue(self, config):
+ """添加任务到队列"""
+ task_id = self.task_manager.add_task(config)
+ self.status_bar.showMessage(f"任务已添加到队列 (ID: {task_id})", 3000)
+
+ def _on_create_schedule(self, name: str, task_codes: list, task_config: dict):
+ """创建调度任务"""
+ # 打开调度编辑对话框
+ from .widgets.task_manager import ScheduleEditDialog
+ from .models.schedule_model import ScheduledTask, ScheduleConfig
+ import uuid
+
+ # 创建一个预填充的调度任务
+ task = ScheduledTask(
+ id=str(uuid.uuid4())[:8],
+ name=name,
+ task_codes=task_codes,
+ schedule=ScheduleConfig(),
+ task_config=task_config,
+ )
+
+ # 打开编辑对话框
+ dialog = ScheduleEditDialog(task=task, parent=self)
+ if dialog.exec():
+ updated_task = dialog.get_task()
+ if updated_task:
+ self.task_manager.schedule_store.add_task(updated_task)
+ self.task_manager._refresh_schedule_table()
+ self.status_bar.showMessage(f"调度任务已创建: {updated_task.name}", 3000)
+ # 切换到任务管理面板的调度选项卡
+ self._switch_panel(1)
+
+ def _show_settings(self):
+ """显示设置对话框"""
+ from .widgets.settings_dialog import SettingsDialog
+ dialog = SettingsDialog(self)
+ if dialog.exec():
+ # 重新加载配置
+ self._refresh_config()
+ self.status_bar.showMessage("设置已保存", 3000)
+
+ def _check_config_on_startup(self):
+ """启动时检查配置"""
+ from .utils.app_settings import app_settings
+ if not app_settings.is_configured():
+ QMessageBox.information(
+ self,
+ "首次配置",
+ "欢迎使用 ETL 管理系统!\n\n"
+ "请先配置 ETL 项目路径,否则无法执行任务。\n\n"
+ "点击 文件 → 设置 进行配置。"
+ )
+
+ def _show_about(self):
+ """显示关于对话框"""
+ QMessageBox.about(
+ self,
+ "关于 飞球 ETL 管理系统",
+ "飞球 ETL 管理系统
"
+ "版本: 1.0.0
"
+ "一个用于管理台球场门店数据 ETL 的图形化工具。
"
+ "功能包括:
"
+ ""
+ "- 任务配置与执行
"
+ "- 环境变量管理
"
+ "- 数据库查询
"
+ "- ETL 状态监控
"
+ "
"
+ )
+
+ def closeEvent(self, event):
+ """关闭事件"""
+ # 检查是否有正在运行的任务
+ if hasattr(self, 'task_panel') and self.task_panel.is_running():
+ reply = QMessageBox.question(
+ self,
+ "确认退出",
+ "当前有任务正在执行,确定要退出吗?",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.No
+ )
+ if reply == QMessageBox.No:
+ event.ignore()
+ return
+
+ # 关闭数据库连接
+ if hasattr(self, 'db_viewer'):
+ self.db_viewer.close_connection()
+
+ event.accept()
diff --git a/etl_billiards/gui/models/__init__.py b/etl_billiards/gui/models/__init__.py
new file mode 100644
index 0000000..cdcbb76
--- /dev/null
+++ b/etl_billiards/gui/models/__init__.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+"""数据模型模块"""
+
+from .task_model import TaskItem, TaskStatus, TaskHistory, TaskConfig, QueuedTask
+from .schedule_model import (
+ ScheduledTask, ScheduleConfig, ScheduleType, IntervalUnit, ScheduleStore
+)
+
+__all__ = [
+ "TaskItem",
+ "TaskStatus",
+ "TaskHistory",
+ "TaskConfig",
+ "QueuedTask",
+ "ScheduledTask",
+ "ScheduleConfig",
+ "ScheduleType",
+ "IntervalUnit",
+ "ScheduleStore",
+]
diff --git a/etl_billiards/gui/models/schedule_model.py b/etl_billiards/gui/models/schedule_model.py
new file mode 100644
index 0000000..6a84f67
--- /dev/null
+++ b/etl_billiards/gui/models/schedule_model.py
@@ -0,0 +1,391 @@
+# -*- coding: utf-8 -*-
+"""调度任务数据模型"""
+
+import json
+from dataclasses import dataclass, field, asdict
+from datetime import datetime, timedelta
+from enum import Enum
+from typing import Optional, List, Dict, Any
+from pathlib import Path
+
+
+class ScheduleType(Enum):
+ """调度类型"""
+ ONCE = "once" # 一次性
+ INTERVAL = "interval" # 固定间隔
+ DAILY = "daily" # 每天
+ WEEKLY = "weekly" # 每周
+ CRON = "cron" # Cron 表达式
+
+
+class IntervalUnit(Enum):
+ """间隔单位"""
+ MINUTES = "minutes"
+ HOURS = "hours"
+ DAYS = "days"
+
+
+@dataclass
+class ScheduleConfig:
+ """调度配置"""
+ schedule_type: ScheduleType = ScheduleType.ONCE
+
+ # 间隔调度
+ interval_value: int = 1
+ interval_unit: IntervalUnit = IntervalUnit.HOURS
+
+ # 每日调度
+ daily_time: str = "04:00" # HH:MM
+
+ # 每周调度
+ weekly_days: List[int] = field(default_factory=lambda: [1]) # 1-7, 1=周一
+ weekly_time: str = "04:00"
+
+ # Cron 表达式
+ cron_expression: str = "0 4 * * *"
+
+ # 通用设置
+ enabled: bool = True
+ start_date: Optional[str] = None # YYYY-MM-DD
+ end_date: Optional[str] = None # YYYY-MM-DD
+
+ def to_dict(self) -> dict:
+ """转换为字典"""
+ return {
+ "schedule_type": self.schedule_type.value,
+ "interval_value": self.interval_value,
+ "interval_unit": self.interval_unit.value,
+ "daily_time": self.daily_time,
+ "weekly_days": self.weekly_days,
+ "weekly_time": self.weekly_time,
+ "cron_expression": self.cron_expression,
+ "enabled": self.enabled,
+ "start_date": self.start_date,
+ "end_date": self.end_date,
+ }
+
+ @classmethod
+ def from_dict(cls, data: dict) -> "ScheduleConfig":
+ """从字典创建"""
+ return cls(
+ schedule_type=ScheduleType(data.get("schedule_type", "once")),
+ interval_value=data.get("interval_value", 1),
+ interval_unit=IntervalUnit(data.get("interval_unit", "hours")),
+ daily_time=data.get("daily_time", "04:00"),
+ weekly_days=data.get("weekly_days", [1]),
+ weekly_time=data.get("weekly_time", "04:00"),
+ cron_expression=data.get("cron_expression", "0 4 * * *"),
+ enabled=data.get("enabled", True),
+ start_date=data.get("start_date"),
+ end_date=data.get("end_date"),
+ )
+
+ def get_description(self) -> str:
+ """获取调度描述"""
+ if self.schedule_type == ScheduleType.ONCE:
+ return "一次性执行"
+ elif self.schedule_type == ScheduleType.INTERVAL:
+ unit_names = {"minutes": "分钟", "hours": "小时", "days": "天"}
+ return f"每 {self.interval_value} {unit_names[self.interval_unit.value]}"
+ elif self.schedule_type == ScheduleType.DAILY:
+ return f"每天 {self.daily_time}"
+ elif self.schedule_type == ScheduleType.WEEKLY:
+ day_names = {1: "一", 2: "二", 3: "三", 4: "四", 5: "五", 6: "六", 7: "日"}
+ days = "、".join(f"周{day_names[d]}" for d in sorted(self.weekly_days))
+ return f"每周 {days} {self.weekly_time}"
+ elif self.schedule_type == ScheduleType.CRON:
+ return f"Cron: {self.cron_expression}"
+ return "未知"
+
+ # 首次执行延迟秒数
+ FIRST_RUN_DELAY_SECONDS = 60
+
+ def get_next_run_time(self, last_run: Optional[datetime] = None) -> Optional[datetime]:
+ """计算下次运行时间
+
+ 注意:首次执行(last_run 为 None)时会延迟 60 秒,避免创建后立即执行
+ """
+ now = datetime.now()
+
+ # 检查日期范围
+ if self.start_date:
+ start = datetime.strptime(self.start_date, "%Y-%m-%d")
+ if now < start:
+ now = start
+
+ if self.end_date:
+ end = datetime.strptime(self.end_date, "%Y-%m-%d") + timedelta(days=1)
+ if now >= end:
+ return None
+
+ # 首次执行延迟 60 秒
+ first_run_time = now + timedelta(seconds=self.FIRST_RUN_DELAY_SECONDS)
+
+ if self.schedule_type == ScheduleType.ONCE:
+ return None if last_run else first_run_time
+
+ elif self.schedule_type == ScheduleType.INTERVAL:
+ if not last_run:
+ return first_run_time
+ if self.interval_unit == IntervalUnit.MINUTES:
+ delta = timedelta(minutes=self.interval_value)
+ elif self.interval_unit == IntervalUnit.HOURS:
+ delta = timedelta(hours=self.interval_value)
+ else:
+ delta = timedelta(days=self.interval_value)
+ return last_run + delta
+
+ elif self.schedule_type == ScheduleType.DAILY:
+ hour, minute = map(int, self.daily_time.split(":"))
+ next_run = now.replace(hour=hour, minute=minute, second=0, microsecond=0)
+ if next_run <= now:
+ next_run += timedelta(days=1)
+ return next_run
+
+ elif self.schedule_type == ScheduleType.WEEKLY:
+ hour, minute = map(int, self.weekly_time.split(":"))
+ # 找到下一个匹配的日期
+ for i in range(8):
+ check_date = now + timedelta(days=i)
+ weekday = check_date.isoweekday() # 1-7
+ if weekday in self.weekly_days:
+ next_run = check_date.replace(hour=hour, minute=minute, second=0, microsecond=0)
+ if next_run > now:
+ return next_run
+ return None
+
+ elif self.schedule_type == ScheduleType.CRON:
+ # 简化版 Cron 解析(只支持基本格式)
+ try:
+ return self._parse_simple_cron(now)
+ except Exception:
+ return None
+
+ return None
+
+ def _parse_simple_cron(self, now: datetime) -> Optional[datetime]:
+ """简化版 Cron 解析"""
+ parts = self.cron_expression.split()
+ if len(parts) != 5:
+ return None
+
+ minute, hour, day, month, weekday = parts
+
+ # 只处理简单情况
+ if minute.isdigit() and hour.isdigit():
+ next_run = now.replace(
+ hour=int(hour),
+ minute=int(minute),
+ second=0,
+ microsecond=0
+ )
+ if next_run <= now:
+ next_run += timedelta(days=1)
+ return next_run
+
+ return None
+
+
+@dataclass
+class ScheduleExecutionRecord:
+ """调度执行记录"""
+ task_id: str # 关联的 QueuedTask ID
+ executed_at: datetime # 执行时间
+ status: str = "" # 状态:success, failed, pending
+ exit_code: Optional[int] = None # 退出码
+ duration_seconds: float = 0.0 # 耗时(秒)
+ summary: str = "" # 执行摘要
+ output: str = "" # 完整执行日志
+ error: str = "" # 错误信息
+
+ # 日志最大长度限制(字符数)
+ MAX_OUTPUT_LENGTH: int = 100000 # 100KB
+
+ def to_dict(self) -> dict:
+ return {
+ "task_id": self.task_id,
+ "executed_at": self.executed_at.isoformat(),
+ "status": self.status,
+ "exit_code": self.exit_code,
+ "duration_seconds": self.duration_seconds,
+ "summary": self.summary,
+ "output": self.output[:self.MAX_OUTPUT_LENGTH] if self.output else "",
+ "error": self.error[:5000] if self.error else "",
+ }
+
+ @classmethod
+ def from_dict(cls, data: dict) -> "ScheduleExecutionRecord":
+ return cls(
+ task_id=data.get("task_id", ""),
+ executed_at=datetime.fromisoformat(data["executed_at"]) if data.get("executed_at") else datetime.now(),
+ status=data.get("status", ""),
+ exit_code=data.get("exit_code"),
+ duration_seconds=data.get("duration_seconds", 0.0),
+ summary=data.get("summary", ""),
+ output=data.get("output", ""),
+ error=data.get("error", ""),
+ )
+
+
+@dataclass
+class ScheduledTask:
+ """调度任务"""
+ id: str
+ name: str
+ task_codes: List[str]
+ schedule: ScheduleConfig
+ task_config: Dict[str, Any] = field(default_factory=dict)
+
+ # 运行状态
+ enabled: bool = True
+ last_run: Optional[datetime] = None
+ next_run: Optional[datetime] = None
+ run_count: int = 0
+ last_status: str = ""
+
+ # 执行历史(最近 N 次执行记录)
+ execution_history: List[ScheduleExecutionRecord] = field(default_factory=list)
+ MAX_HISTORY_SIZE: int = field(default=50, repr=False) # 保留最近50次执行记录
+
+ created_at: datetime = field(default_factory=datetime.now)
+ updated_at: datetime = field(default_factory=datetime.now)
+
+ def add_execution_record(self, record: ScheduleExecutionRecord):
+ """添加执行记录"""
+ self.execution_history.insert(0, record)
+ # 限制历史记录数量
+ if len(self.execution_history) > self.MAX_HISTORY_SIZE:
+ self.execution_history = self.execution_history[:self.MAX_HISTORY_SIZE]
+
+ def update_execution_record(self, task_id: str, status: str, exit_code: int, duration: float,
+ summary: str, output: str = "", error: str = ""):
+ """更新执行记录状态"""
+ for record in self.execution_history:
+ if record.task_id == task_id:
+ record.status = status
+ record.exit_code = exit_code
+ record.duration_seconds = duration
+ record.summary = summary
+ record.output = output
+ record.error = error
+ break
+
+ def to_dict(self) -> dict:
+ """转换为字典"""
+ return {
+ "id": self.id,
+ "name": self.name,
+ "task_codes": self.task_codes,
+ "schedule": self.schedule.to_dict(),
+ "task_config": self.task_config,
+ "enabled": self.enabled,
+ "last_run": self.last_run.isoformat() if self.last_run else None,
+ "next_run": self.next_run.isoformat() if self.next_run else None,
+ "run_count": self.run_count,
+ "last_status": self.last_status,
+ "execution_history": [r.to_dict() for r in self.execution_history],
+ "created_at": self.created_at.isoformat(),
+ "updated_at": self.updated_at.isoformat(),
+ }
+
+ @classmethod
+ def from_dict(cls, data: dict) -> "ScheduledTask":
+ """从字典创建"""
+ history_data = data.get("execution_history", [])
+ execution_history = [ScheduleExecutionRecord.from_dict(r) for r in history_data]
+
+ return cls(
+ id=data["id"],
+ name=data["name"],
+ task_codes=data["task_codes"],
+ schedule=ScheduleConfig.from_dict(data.get("schedule", {})),
+ task_config=data.get("task_config", {}),
+ enabled=data.get("enabled", True),
+ last_run=datetime.fromisoformat(data["last_run"]) if data.get("last_run") else None,
+ next_run=datetime.fromisoformat(data["next_run"]) if data.get("next_run") else None,
+ run_count=data.get("run_count", 0),
+ last_status=data.get("last_status", ""),
+ execution_history=execution_history,
+ created_at=datetime.fromisoformat(data["created_at"]) if data.get("created_at") else datetime.now(),
+ updated_at=datetime.fromisoformat(data["updated_at"]) if data.get("updated_at") else datetime.now(),
+ )
+
+ def update_next_run(self):
+ """更新下次运行时间"""
+ if self.enabled and self.schedule.enabled:
+ self.next_run = self.schedule.get_next_run_time(self.last_run)
+ else:
+ self.next_run = None
+ self.updated_at = datetime.now()
+
+
+class ScheduleStore:
+ """调度任务存储"""
+
+ def __init__(self, storage_path: Optional[Path] = None):
+ if storage_path is None:
+ storage_path = Path(__file__).resolve().parents[2] / "scheduled_tasks.json"
+ self.storage_path = storage_path
+ self.tasks: Dict[str, ScheduledTask] = {}
+ self.load()
+
+ def load(self):
+ """加载任务"""
+ if self.storage_path.exists():
+ try:
+ data = json.loads(self.storage_path.read_text(encoding="utf-8"))
+ self.tasks = {
+ task_id: ScheduledTask.from_dict(task_data)
+ for task_id, task_data in data.get("tasks", {}).items()
+ }
+ except Exception:
+ self.tasks = {}
+
+ def save(self):
+ """保存任务"""
+ data = {
+ "tasks": {
+ task_id: task.to_dict()
+ for task_id, task in self.tasks.items()
+ }
+ }
+ self.storage_path.write_text(
+ json.dumps(data, ensure_ascii=False, indent=2),
+ encoding="utf-8"
+ )
+
+ def add_task(self, task: ScheduledTask):
+ """添加任务"""
+ task.update_next_run()
+ self.tasks[task.id] = task
+ self.save()
+
+ def remove_task(self, task_id: str):
+ """移除任务"""
+ if task_id in self.tasks:
+ del self.tasks[task_id]
+ self.save()
+
+ def update_task(self, task: ScheduledTask):
+ """更新任务"""
+ task.update_next_run()
+ task.updated_at = datetime.now()
+ self.tasks[task.id] = task
+ self.save()
+
+ def get_task(self, task_id: str) -> Optional[ScheduledTask]:
+ """获取任务"""
+ return self.tasks.get(task_id)
+
+ def get_all_tasks(self) -> List[ScheduledTask]:
+ """获取所有任务"""
+ return list(self.tasks.values())
+
+ def get_due_tasks(self) -> List[ScheduledTask]:
+ """获取到期需要执行的任务"""
+ now = datetime.now()
+ due_tasks = []
+ for task in self.tasks.values():
+ if task.enabled and task.next_run and task.next_run <= now:
+ due_tasks.append(task)
+ return due_tasks
diff --git a/etl_billiards/gui/models/task_model.py b/etl_billiards/gui/models/task_model.py
new file mode 100644
index 0000000..a9732b5
--- /dev/null
+++ b/etl_billiards/gui/models/task_model.py
@@ -0,0 +1,179 @@
+# -*- coding: utf-8 -*-
+"""任务数据模型"""
+
+from dataclasses import dataclass, field
+from datetime import datetime
+from enum import Enum
+from typing import Optional, List, Dict, Any
+
+
+class TaskStatus(Enum):
+ """任务状态枚举"""
+ PENDING = "pending" # 待执行
+ RUNNING = "running" # 执行中
+ SUCCESS = "success" # 成功
+ FAILED = "failed" # 失败
+ CANCELLED = "cancelled" # 已取消
+
+
+class TaskCategory(Enum):
+ """任务分类"""
+ ODS = "ODS" # ODS 数据抓取任务
+ DWD = "DWD" # DWD 装载任务
+ DWS = "DWS" # DWS 汇总任务
+ SCHEMA = "Schema" # Schema 初始化任务
+ QUALITY = "Quality" # 质量检查任务
+ OTHER = "Other" # 其他任务
+
+
+# 任务分类映射
+TASK_CATEGORIES: Dict[str, TaskCategory] = {
+ # ODS 任务
+ "ODS_PAYMENT": TaskCategory.ODS,
+ "ODS_MEMBER": TaskCategory.ODS,
+ "ODS_MEMBER_CARD": TaskCategory.ODS,
+ "ODS_MEMBER_BALANCE": TaskCategory.ODS,
+ "ODS_SETTLEMENT_RECORDS": TaskCategory.ODS,
+ "ODS_TABLE_USE": TaskCategory.ODS,
+ "ODS_ASSISTANT_ACCOUNT": TaskCategory.ODS,
+ "ODS_ASSISTANT_LEDGER": TaskCategory.ODS,
+ "ODS_ASSISTANT_ABOLISH": TaskCategory.ODS,
+ "ODS_REFUND": TaskCategory.ODS,
+ "ODS_PLATFORM_COUPON": TaskCategory.ODS,
+ "ODS_RECHARGE_SETTLE": TaskCategory.ODS,
+ "ODS_GROUP_PACKAGE": TaskCategory.ODS,
+ "ODS_GROUP_BUY_REDEMPTION": TaskCategory.ODS,
+ "ODS_INVENTORY_STOCK": TaskCategory.ODS,
+ "ODS_INVENTORY_CHANGE": TaskCategory.ODS,
+ "ODS_TABLES": TaskCategory.ODS,
+ "ODS_GOODS_CATEGORY": TaskCategory.ODS,
+ "ODS_STORE_GOODS": TaskCategory.ODS,
+ "ODS_STORE_GOODS_SALES": TaskCategory.ODS,
+ "ODS_TABLE_FEE_DISCOUNT": TaskCategory.ODS,
+ "ODS_TENANT_GOODS": TaskCategory.ODS,
+ "ODS_SETTLEMENT_TICKET": TaskCategory.ODS,
+ # DWD 任务
+ "DWD_LOAD_FROM_ODS": TaskCategory.DWD,
+ "DWD_QUALITY_CHECK": TaskCategory.QUALITY,
+ "PAYMENTS_DWD": TaskCategory.DWD,
+ "MEMBERS_DWD": TaskCategory.DWD,
+ "TICKET_DWD": TaskCategory.DWD,
+ # DWS 任务
+ "INIT_DWS_SCHEMA": TaskCategory.SCHEMA,
+ "DWS_BUILD_ORDER_SUMMARY": TaskCategory.DWS,
+ # Schema 任务
+ "INIT_ODS_SCHEMA": TaskCategory.SCHEMA,
+ "INIT_DWD_SCHEMA": TaskCategory.SCHEMA,
+ # 其他任务
+ "MANUAL_INGEST": TaskCategory.OTHER,
+ "CHECK_CUTOFF": TaskCategory.OTHER,
+ "DATA_INTEGRITY_CHECK": TaskCategory.QUALITY,
+ "ODS_JSON_ARCHIVE": TaskCategory.OTHER,
+ # 旧版任务(兼容)
+ "PRODUCTS": TaskCategory.ODS,
+ "TABLES": TaskCategory.ODS,
+ "MEMBERS": TaskCategory.ODS,
+ "ASSISTANTS": TaskCategory.ODS,
+ "PACKAGES_DEF": TaskCategory.ODS,
+ "ORDERS": TaskCategory.ODS,
+ "PAYMENTS": TaskCategory.ODS,
+ "REFUNDS": TaskCategory.ODS,
+ "COUPON_USAGE": TaskCategory.ODS,
+ "INVENTORY_CHANGE": TaskCategory.ODS,
+ "TOPUPS": TaskCategory.ODS,
+ "TABLE_DISCOUNT": TaskCategory.ODS,
+ "ASSISTANT_ABOLISH": TaskCategory.ODS,
+ "LEDGER": TaskCategory.ODS,
+}
+
+
+def get_task_category(task_code: str) -> TaskCategory:
+ """获取任务分类"""
+ return TASK_CATEGORIES.get(task_code.upper(), TaskCategory.OTHER)
+
+
+@dataclass
+class TaskItem:
+ """任务项"""
+ task_code: str
+ name: str = ""
+ description: str = ""
+ category: TaskCategory = TaskCategory.OTHER
+ enabled: bool = True
+
+ def __post_init__(self):
+ if not self.name:
+ self.name = self.task_code
+ if not self.category or self.category == TaskCategory.OTHER:
+ self.category = get_task_category(self.task_code)
+
+
+@dataclass
+class TaskConfig:
+ """任务执行配置"""
+ tasks: List[str] = field(default_factory=list)
+ pipeline_flow: str = "FULL" # FULL, FETCH_ONLY, INGEST_ONLY
+ dry_run: bool = False
+ window_start: Optional[str] = None
+ window_end: Optional[str] = None
+ window_split: Optional[str] = None # none, month
+ window_compensation: int = 0 # 补偿小时数
+ ingest_source: Optional[str] = None
+ store_id: Optional[int] = None
+ pg_dsn: Optional[str] = None
+ api_token: Optional[str] = None
+ extra_args: Dict[str, Any] = field(default_factory=dict)
+ env_vars: Dict[str, str] = field(default_factory=dict) # 额外环境变量
+
+
+@dataclass
+class TaskHistory:
+ """任务执行历史"""
+ id: str
+ task_codes: List[str]
+ status: TaskStatus
+ start_time: datetime
+ end_time: Optional[datetime] = None
+ exit_code: Optional[int] = None
+ command: str = ""
+ output_log: str = ""
+ error_message: str = ""
+ summary: Dict[str, Any] = field(default_factory=dict)
+
+ @property
+ def duration_seconds(self) -> Optional[float]:
+ """执行时长(秒)"""
+ if self.end_time and self.start_time:
+ return (self.end_time - self.start_time).total_seconds()
+ return None
+
+ @property
+ def duration_str(self) -> str:
+ """格式化的执行时长"""
+ secs = self.duration_seconds
+ if secs is None:
+ return "-"
+ if secs < 60:
+ return f"{secs:.1f}秒"
+ elif secs < 3600:
+ mins = int(secs // 60)
+ secs = secs % 60
+ return f"{mins}分{secs:.0f}秒"
+ else:
+ hours = int(secs // 3600)
+ mins = int((secs % 3600) // 60)
+ return f"{hours}时{mins}分"
+
+
+@dataclass
+class QueuedTask:
+ """队列中的任务"""
+ id: str
+ config: TaskConfig
+ status: TaskStatus = TaskStatus.PENDING
+ created_at: datetime = field(default_factory=datetime.now)
+ started_at: Optional[datetime] = None
+ finished_at: Optional[datetime] = None
+ output: str = ""
+ error: str = ""
+ exit_code: Optional[int] = None
diff --git a/etl_billiards/gui/resources/__init__.py b/etl_billiards/gui/resources/__init__.py
new file mode 100644
index 0000000..ef67034
--- /dev/null
+++ b/etl_billiards/gui/resources/__init__.py
@@ -0,0 +1,14 @@
+# -*- coding: utf-8 -*-
+"""GUI 资源模块"""
+
+from pathlib import Path
+
+RESOURCES_DIR = Path(__file__).parent
+STYLES_PATH = RESOURCES_DIR / "styles.qss"
+
+
+def load_stylesheet() -> str:
+ """加载样式表"""
+ if STYLES_PATH.exists():
+ return STYLES_PATH.read_text(encoding="utf-8")
+ return ""
diff --git a/etl_billiards/gui/resources/styles.qss b/etl_billiards/gui/resources/styles.qss
new file mode 100644
index 0000000..84457dc
--- /dev/null
+++ b/etl_billiards/gui/resources/styles.qss
@@ -0,0 +1,458 @@
+/* ETL GUI 现代浅色主题样式表 */
+
+/* ========== 全局样式 ========== */
+QWidget {
+ font-family: "Microsoft YaHei", "Segoe UI", sans-serif;
+ font-size: 13px;
+ color: #333333;
+ background-color: #f5f5f5;
+}
+
+QMainWindow {
+ background-color: #f5f5f5;
+}
+
+/* ========== 菜单栏 ========== */
+QMenuBar {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e0e0e0;
+ padding: 4px;
+}
+
+QMenuBar::item {
+ padding: 6px 12px;
+ background-color: transparent;
+ border-radius: 4px;
+}
+
+QMenuBar::item:selected {
+ background-color: #e8f0fe;
+}
+
+QMenu {
+ background-color: #ffffff;
+ border: 1px solid #e0e0e0;
+ border-radius: 8px;
+ padding: 4px;
+}
+
+QMenu::item {
+ padding: 8px 24px;
+ border-radius: 4px;
+}
+
+QMenu::item:selected {
+ background-color: #e8f0fe;
+}
+
+/* ========== 工具栏 ========== */
+QToolBar {
+ background-color: #ffffff;
+ border-bottom: 1px solid #e0e0e0;
+ padding: 4px;
+ spacing: 4px;
+}
+
+QToolButton {
+ background-color: transparent;
+ border: none;
+ border-radius: 6px;
+ padding: 8px;
+}
+
+QToolButton:hover {
+ background-color: #e8f0fe;
+}
+
+QToolButton:pressed {
+ background-color: #d2e3fc;
+}
+
+/* ========== 按钮 ========== */
+QPushButton {
+ background-color: #1a73e8;
+ color: white;
+ border: none;
+ border-radius: 6px;
+ padding: 8px 16px;
+ font-weight: 500;
+}
+
+QPushButton:hover {
+ background-color: #1557b0;
+}
+
+QPushButton:pressed {
+ background-color: #104080;
+}
+
+QPushButton:disabled {
+ background-color: #dadce0;
+ color: #9aa0a6;
+}
+
+QPushButton[secondary="true"] {
+ background-color: #ffffff;
+ color: #1a73e8;
+ border: 1px solid #dadce0;
+}
+
+QPushButton[secondary="true"]:hover {
+ background-color: #f8f9fa;
+ border-color: #1a73e8;
+}
+
+QPushButton[danger="true"] {
+ background-color: #ea4335;
+}
+
+QPushButton[danger="true"]:hover {
+ background-color: #c5221f;
+}
+
+/* ========== 输入框 ========== */
+QLineEdit, QTextEdit, QPlainTextEdit {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 6px;
+ padding: 8px 12px;
+ selection-background-color: #d2e3fc;
+}
+
+QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus {
+ border-color: #1a73e8;
+ border-width: 2px;
+ padding: 7px 11px;
+}
+
+QLineEdit:disabled, QTextEdit:disabled, QPlainTextEdit:disabled {
+ background-color: #f1f3f4;
+ color: #9aa0a6;
+}
+
+/* ========== 下拉框 ========== */
+QComboBox {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 6px;
+ padding: 8px 12px;
+ padding-right: 30px;
+}
+
+QComboBox:hover {
+ border-color: #1a73e8;
+}
+
+QComboBox:focus {
+ border-color: #1a73e8;
+ border-width: 2px;
+}
+
+QComboBox::drop-down {
+ border: none;
+ width: 24px;
+}
+
+QComboBox::down-arrow {
+ image: none;
+ border-left: 5px solid transparent;
+ border-right: 5px solid transparent;
+ border-top: 6px solid #5f6368;
+ margin-right: 8px;
+}
+
+QComboBox QAbstractItemView {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ selection-background-color: #e8f0fe;
+}
+
+/* ========== 复选框 ========== */
+QCheckBox {
+ spacing: 8px;
+}
+
+QCheckBox::indicator {
+ width: 18px;
+ height: 18px;
+ border-radius: 4px;
+ border: 2px solid #5f6368;
+}
+
+QCheckBox::indicator:checked {
+ background-color: #1a73e8;
+ border-color: #1a73e8;
+}
+
+QCheckBox::indicator:hover {
+ border-color: #1a73e8;
+}
+
+/* ========== 列表和树 ========== */
+QListWidget, QTreeWidget, QTableWidget {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ outline: none;
+}
+
+QListWidget::item, QTreeWidget::item {
+ padding: 8px;
+ border-radius: 4px;
+}
+
+QListWidget::item:selected, QTreeWidget::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+}
+
+QListWidget::item:hover, QTreeWidget::item:hover {
+ background-color: #f8f9fa;
+}
+
+QHeaderView::section {
+ background-color: #f8f9fa;
+ border: none;
+ border-bottom: 1px solid #dadce0;
+ padding: 10px 16px;
+ font-weight: 600;
+}
+
+QTableWidget {
+ gridline-color: #e8eaed;
+}
+
+QTableWidget::item {
+ padding: 8px;
+}
+
+QTableWidget::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+}
+
+/* ========== 滚动条 ========== */
+QScrollBar:vertical {
+ background-color: transparent;
+ width: 12px;
+ margin: 0;
+}
+
+QScrollBar::handle:vertical {
+ background-color: #dadce0;
+ border-radius: 6px;
+ min-height: 30px;
+ margin: 2px;
+}
+
+QScrollBar::handle:vertical:hover {
+ background-color: #bdc1c6;
+}
+
+QScrollBar::add-line:vertical, QScrollBar::sub-line:vertical {
+ height: 0;
+}
+
+QScrollBar:horizontal {
+ background-color: transparent;
+ height: 12px;
+ margin: 0;
+}
+
+QScrollBar::handle:horizontal {
+ background-color: #dadce0;
+ border-radius: 6px;
+ min-width: 30px;
+ margin: 2px;
+}
+
+QScrollBar::handle:horizontal:hover {
+ background-color: #bdc1c6;
+}
+
+QScrollBar::add-line:horizontal, QScrollBar::sub-line:horizontal {
+ width: 0;
+}
+
+/* ========== 选项卡 ========== */
+QTabWidget::pane {
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ background-color: #ffffff;
+ margin-top: -1px;
+}
+
+QTabBar::tab {
+ background-color: transparent;
+ border: none;
+ padding: 10px 20px;
+ margin-right: 4px;
+ color: #5f6368;
+}
+
+QTabBar::tab:selected {
+ color: #1a73e8;
+ border-bottom: 2px solid #1a73e8;
+}
+
+QTabBar::tab:hover:!selected {
+ background-color: #f8f9fa;
+ border-radius: 6px 6px 0 0;
+}
+
+/* ========== 分组框 ========== */
+QGroupBox {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 8px;
+ margin-top: 16px;
+ padding: 16px;
+ padding-top: 24px;
+}
+
+QGroupBox::title {
+ subcontrol-origin: margin;
+ subcontrol-position: top left;
+ left: 16px;
+ padding: 0 8px;
+ background-color: #ffffff;
+ color: #5f6368;
+ font-weight: 600;
+}
+
+/* ========== 进度条 ========== */
+QProgressBar {
+ background-color: #e8eaed;
+ border: none;
+ border-radius: 4px;
+ height: 8px;
+ text-align: center;
+}
+
+QProgressBar::chunk {
+ background-color: #1a73e8;
+ border-radius: 4px;
+}
+
+/* ========== 分割器 ========== */
+QSplitter::handle {
+ background-color: #e0e0e0;
+}
+
+QSplitter::handle:horizontal {
+ width: 2px;
+}
+
+QSplitter::handle:vertical {
+ height: 2px;
+}
+
+QSplitter::handle:hover {
+ background-color: #1a73e8;
+}
+
+/* ========== 状态栏 ========== */
+QStatusBar {
+ background-color: #ffffff;
+ border-top: 1px solid #e0e0e0;
+ padding: 4px;
+}
+
+QStatusBar::item {
+ border: none;
+}
+
+/* ========== 提示框 ========== */
+QToolTip {
+ background-color: #3c4043;
+ color: #ffffff;
+ border: none;
+ border-radius: 4px;
+ padding: 8px 12px;
+}
+
+/* ========== 消息框 ========== */
+QMessageBox {
+ background-color: #ffffff;
+}
+
+/* ========== 导航侧边栏 ========== */
+QListWidget#navList {
+ background-color: #ffffff;
+ border: none;
+ border-right: 1px solid #e0e0e0;
+ padding: 8px;
+}
+
+QListWidget#navList::item {
+ padding: 12px 16px;
+ border-radius: 8px;
+ margin: 2px 0;
+}
+
+QListWidget#navList::item:selected {
+ background-color: #e8f0fe;
+ color: #1a73e8;
+ font-weight: 600;
+}
+
+/* ========== 日志查看器 ========== */
+QPlainTextEdit#logViewer {
+ font-family: "Consolas", "Courier New", monospace;
+ font-size: 12px;
+ background-color: #fafafa;
+ line-height: 1.5;
+}
+
+/* ========== SQL 编辑器 ========== */
+QPlainTextEdit#sqlEditor {
+ font-family: "Consolas", "Courier New", monospace;
+ font-size: 13px;
+ background-color: #ffffff;
+}
+
+/* ========== 卡片样式 ========== */
+QFrame[card="true"] {
+ background-color: #ffffff;
+ border: 1px solid #dadce0;
+ border-radius: 12px;
+ padding: 16px;
+}
+
+QFrame[card="true"]:hover {
+ border-color: #1a73e8;
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+/* ========== 标签 ========== */
+QLabel[heading="true"] {
+ font-size: 18px;
+ font-weight: 600;
+ color: #202124;
+}
+
+QLabel[subheading="true"] {
+ font-size: 14px;
+ color: #5f6368;
+}
+
+QLabel[status="success"] {
+ color: #1e8e3e;
+ font-weight: 500;
+}
+
+QLabel[status="error"] {
+ color: #d93025;
+ font-weight: 500;
+}
+
+QLabel[status="warning"] {
+ color: #f9ab00;
+ font-weight: 500;
+}
+
+QLabel[status="info"] {
+ color: #1a73e8;
+ font-weight: 500;
+}
diff --git a/etl_billiards/gui/utils/__init__.py b/etl_billiards/gui/utils/__init__.py
new file mode 100644
index 0000000..fcb45e1
--- /dev/null
+++ b/etl_billiards/gui/utils/__init__.py
@@ -0,0 +1,8 @@
+# -*- coding: utf-8 -*-
+"""工具模块"""
+
+from .cli_builder import CLIBuilder
+from .config_helper import ConfigHelper
+from .app_settings import app_settings, AppSettings
+
+__all__ = ["CLIBuilder", "ConfigHelper", "app_settings", "AppSettings"]
diff --git a/etl_billiards/gui/utils/app_settings.py b/etl_billiards/gui/utils/app_settings.py
new file mode 100644
index 0000000..1089de3
--- /dev/null
+++ b/etl_billiards/gui/utils/app_settings.py
@@ -0,0 +1,434 @@
+# -*- coding: utf-8 -*-
+"""应用程序设置管理"""
+
+import json
+import os
+import sys
+from pathlib import Path
+from typing import Any, Dict, Optional
+
+
+class AppSettings:
+ """应用程序设置单例"""
+
+ _instance: Optional["AppSettings"] = None
+
+ def __new__(cls):
+ if cls._instance is None:
+ cls._instance = super().__new__(cls)
+ cls._instance._initialized = False
+ return cls._instance
+
+ def __init__(self):
+ if self._initialized:
+ return
+ self._initialized = True
+
+ # 配置文件路径
+ self._settings_file = self._get_settings_path()
+
+ # 默认设置
+ self._settings = {
+ "etl_project_path": "", # ETL 项目路径
+ "env_file_path": "", # .env 文件路径
+ # 自动更新配置
+ "auto_update": {
+ "hours": 24,
+ "overlap_seconds": 3600,
+ "include_dwd": True,
+ "auto_verify": False,
+ "selected_tasks": [],
+ },
+ # 数据校验配置
+ "integrity_check": {
+ "mode": "history",
+ "history_start": "",
+ "history_end": "",
+ "lookback_hours": 24,
+ "include_dimensions": False,
+ "auto_backfill": False,
+ "ods_tasks": "",
+ },
+ # 高级配置
+ "advanced": {
+ "pipeline_flow": "FULL",
+ "dry_run": False,
+ "window_start": "",
+ "window_end": "",
+ "window_split": "none",
+ "window_compensation": 0,
+ "ingest_source": "",
+ "store_id": "",
+ "pg_dsn": "",
+ "api_token": "",
+ },
+ }
+
+ # 加载设置
+ self._load()
+
+ # 如果没有配置,尝试自动检测
+ if not self._settings["etl_project_path"]:
+ self._auto_detect_paths()
+
+ def _get_settings_path(self) -> Path:
+ """获取设置文件路径"""
+ # 优先使用用户目录
+ if sys.platform == "win32":
+ app_data = os.environ.get("APPDATA", "")
+ if app_data:
+ settings_dir = Path(app_data) / "ETL管理系统"
+ else:
+ settings_dir = Path.home() / ".etl_gui"
+ else:
+ settings_dir = Path.home() / ".etl_gui"
+
+ settings_dir.mkdir(parents=True, exist_ok=True)
+ return settings_dir / "settings.json"
+
+ def _auto_detect_paths(self):
+ """自动检测 ETL 项目路径"""
+ # 方法1: 检查是否从源码目录运行
+ try:
+ source_dir = Path(__file__).resolve().parents[2]
+ cli_main = source_dir / "cli" / "main.py"
+ if cli_main.exists():
+ rel_source = Path(os.path.relpath(source_dir, Path.cwd()))
+ self._settings["etl_project_path"] = str(rel_source)
+ env_file = rel_source / ".env"
+ if env_file.exists():
+ self._settings["env_file_path"] = str(env_file)
+ self._save()
+ return
+ except Exception:
+ pass
+
+ # 方法2: 检查常见位置
+ common_paths = [
+ Path("etl_billiards"),
+ Path("."),
+ ]
+
+ for path in common_paths:
+ if path.exists() and (path / "cli" / "main.py").exists():
+ self._settings["etl_project_path"] = str(path)
+ env_file = path / ".env"
+ if env_file.exists():
+ self._settings["env_file_path"] = str(env_file)
+ self._save()
+ return
+
+ def _load(self):
+ """加载设置"""
+ if self._settings_file.exists():
+ try:
+ data = json.loads(self._settings_file.read_text(encoding="utf-8"))
+ self._settings.update(data)
+ except Exception:
+ pass
+
+ def _save(self):
+ """保存设置"""
+ try:
+ self._settings_file.write_text(
+ json.dumps(self._settings, ensure_ascii=False, indent=2),
+ encoding="utf-8"
+ )
+ except Exception:
+ pass
+
+ @property
+ def etl_project_path(self) -> str:
+ """获取 ETL 项目路径"""
+ return self._settings.get("etl_project_path", "")
+
+ @etl_project_path.setter
+ def etl_project_path(self, value: str):
+ """设置 ETL 项目路径"""
+ self._settings["etl_project_path"] = value
+ # 同时更新 .env 路径
+ if value:
+ env_path = Path(value) / ".env"
+ if env_path.exists():
+ self._settings["env_file_path"] = str(env_path)
+ self._save()
+
+ @property
+ def env_file_path(self) -> str:
+ """获取 .env 文件路径"""
+ path = self._settings.get("env_file_path", "")
+ if not path and self.etl_project_path:
+ path = str(Path(self.etl_project_path) / ".env")
+ return path
+
+ @env_file_path.setter
+ def env_file_path(self, value: str):
+ """设置 .env 文件路径"""
+ self._settings["env_file_path"] = value
+ self._save()
+
+ def is_configured(self) -> bool:
+ """检查是否已配置"""
+ path = self.etl_project_path
+ if not path:
+ return False
+ return Path(path).exists() and (Path(path) / "cli" / "main.py").exists()
+
+ def validate(self) -> tuple[bool, str]:
+ """验证配置"""
+ path = self.etl_project_path
+ if not path:
+ return False, "未配置 ETL 项目路径"
+
+ project_path = Path(path)
+ if not project_path.exists():
+ return False, f"ETL 项目路径不存在: {path}"
+
+ cli_main = project_path / "cli" / "main.py"
+ if not cli_main.exists():
+ return False, f"找不到 CLI 入口: {cli_main}"
+
+ return True, "配置有效"
+
+ # ==================== 自动更新配置 ====================
+
+ @property
+ def auto_update_hours(self) -> int:
+ return self._settings.get("auto_update", {}).get("hours", 24)
+
+ @auto_update_hours.setter
+ def auto_update_hours(self, value: int):
+ self._settings.setdefault("auto_update", {})["hours"] = value
+ self._save()
+
+ @property
+ def auto_update_overlap_seconds(self) -> int:
+ return self._settings.get("auto_update", {}).get("overlap_seconds", 3600)
+
+ @auto_update_overlap_seconds.setter
+ def auto_update_overlap_seconds(self, value: int):
+ self._settings.setdefault("auto_update", {})["overlap_seconds"] = value
+ self._save()
+
+ @property
+ def auto_update_include_dwd(self) -> bool:
+ return self._settings.get("auto_update", {}).get("include_dwd", True)
+
+ @auto_update_include_dwd.setter
+ def auto_update_include_dwd(self, value: bool):
+ self._settings.setdefault("auto_update", {})["include_dwd"] = value
+ self._save()
+
+ @property
+ def auto_update_auto_verify(self) -> bool:
+ return self._settings.get("auto_update", {}).get("auto_verify", False)
+
+ @auto_update_auto_verify.setter
+ def auto_update_auto_verify(self, value: bool):
+ self._settings.setdefault("auto_update", {})["auto_verify"] = value
+ self._save()
+
+ @property
+ def auto_update_selected_tasks(self) -> list:
+ return self._settings.get("auto_update", {}).get("selected_tasks", [])
+
+ @auto_update_selected_tasks.setter
+ def auto_update_selected_tasks(self, value: list):
+ self._settings.setdefault("auto_update", {})["selected_tasks"] = value
+ self._save()
+
+ # ==================== 数据校验配置 ====================
+
+ @property
+ def integrity_mode(self) -> str:
+ return self._settings.get("integrity_check", {}).get("mode", "history")
+
+ @integrity_mode.setter
+ def integrity_mode(self, value: str):
+ self._settings.setdefault("integrity_check", {})["mode"] = value
+ self._save()
+
+ @property
+ def integrity_history_start(self) -> str:
+ return self._settings.get("integrity_check", {}).get("history_start", "")
+
+ @integrity_history_start.setter
+ def integrity_history_start(self, value: str):
+ self._settings.setdefault("integrity_check", {})["history_start"] = value
+ self._save()
+
+ @property
+ def integrity_history_end(self) -> str:
+ return self._settings.get("integrity_check", {}).get("history_end", "")
+
+ @integrity_history_end.setter
+ def integrity_history_end(self, value: str):
+ self._settings.setdefault("integrity_check", {})["history_end"] = value
+ self._save()
+
+ @property
+ def integrity_lookback_hours(self) -> int:
+ return self._settings.get("integrity_check", {}).get("lookback_hours", 24)
+
+ @integrity_lookback_hours.setter
+ def integrity_lookback_hours(self, value: int):
+ self._settings.setdefault("integrity_check", {})["lookback_hours"] = value
+ self._save()
+
+ @property
+ def integrity_include_dimensions(self) -> bool:
+ return self._settings.get("integrity_check", {}).get("include_dimensions", False)
+
+ @integrity_include_dimensions.setter
+ def integrity_include_dimensions(self, value: bool):
+ self._settings.setdefault("integrity_check", {})["include_dimensions"] = value
+ self._save()
+
+ @property
+ def integrity_auto_backfill(self) -> bool:
+ return self._settings.get("integrity_check", {}).get("auto_backfill", False)
+
+ @integrity_auto_backfill.setter
+ def integrity_auto_backfill(self, value: bool):
+ self._settings.setdefault("integrity_check", {})["auto_backfill"] = value
+ self._save()
+
+ @property
+ def integrity_ods_tasks(self) -> str:
+ return self._settings.get("integrity_check", {}).get("ods_tasks", "")
+
+ @integrity_ods_tasks.setter
+ def integrity_ods_tasks(self, value: str):
+ self._settings.setdefault("integrity_check", {})["ods_tasks"] = value
+ self._save()
+
+ # ==================== 高级配置 ====================
+
+ @property
+ def advanced_pipeline_flow(self) -> str:
+ return self._settings.get("advanced", {}).get("pipeline_flow", "FULL")
+
+ @advanced_pipeline_flow.setter
+ def advanced_pipeline_flow(self, value: str):
+ self._settings.setdefault("advanced", {})["pipeline_flow"] = value
+ self._save()
+
+ @property
+ def advanced_dry_run(self) -> bool:
+ return self._settings.get("advanced", {}).get("dry_run", False)
+
+ @advanced_dry_run.setter
+ def advanced_dry_run(self, value: bool):
+ self._settings.setdefault("advanced", {})["dry_run"] = value
+ self._save()
+
+ @property
+ def advanced_window_start(self) -> str:
+ return self._settings.get("advanced", {}).get("window_start", "")
+
+ @advanced_window_start.setter
+ def advanced_window_start(self, value: str):
+ self._settings.setdefault("advanced", {})["window_start"] = value
+ self._save()
+
+ @property
+ def advanced_window_end(self) -> str:
+ return self._settings.get("advanced", {}).get("window_end", "")
+
+ @advanced_window_end.setter
+ def advanced_window_end(self, value: str):
+ self._settings.setdefault("advanced", {})["window_end"] = value
+ self._save()
+
+ @property
+ def advanced_ingest_source(self) -> str:
+ return self._settings.get("advanced", {}).get("ingest_source", "")
+
+ @advanced_ingest_source.setter
+ def advanced_ingest_source(self, value: str):
+ self._settings.setdefault("advanced", {})["ingest_source"] = value
+ self._save()
+
+ @property
+ def advanced_window_split(self) -> str:
+ return self._settings.get("advanced", {}).get("window_split", "none")
+
+ @advanced_window_split.setter
+ def advanced_window_split(self, value: str):
+ self._settings.setdefault("advanced", {})["window_split"] = value
+ self._save()
+
+ @property
+ def advanced_window_compensation(self) -> int:
+ return self._settings.get("advanced", {}).get("window_compensation", 0)
+
+ @advanced_window_compensation.setter
+ def advanced_window_compensation(self, value: int):
+ self._settings.setdefault("advanced", {})["window_compensation"] = value
+ self._save()
+
+ def get_all_settings(self) -> Dict[str, Any]:
+ """获取所有设置(用于调试)"""
+ return self._settings.copy()
+
+ def save_all(self):
+ """强制保存所有设置"""
+ self._save()
+
+ # ==================== 任务历史存储 ====================
+
+ def _get_history_path(self) -> Path:
+ """获取任务历史文件路径"""
+ return self._settings_file.parent / "task_history.json"
+
+ def save_task_history(self, history_list: list):
+ """保存任务历史到文件"""
+ try:
+ history_path = self._get_history_path()
+
+ # 序列化任务历史
+ serialized = []
+ for task in history_list[:100]: # 最多保存100条
+ try:
+ task_data = {
+ "id": task.id,
+ "tasks": task.config.tasks if hasattr(task, 'config') else [],
+ "status": task.status.value if hasattr(task.status, 'value') else str(task.status),
+ "created_at": task.created_at.isoformat() if task.created_at else None,
+ "started_at": task.started_at.isoformat() if task.started_at else None,
+ "finished_at": task.finished_at.isoformat() if task.finished_at else None,
+ "exit_code": task.exit_code,
+ "error": task.error[:500] if task.error else "", # 限制长度
+ "output_preview": task.output[:1000] if task.output else "", # 输出预览
+ # 保存配置信息
+ "pipeline_flow": task.config.pipeline_flow if hasattr(task, 'config') else "FULL",
+ "window_start": task.config.window_start if hasattr(task, 'config') else None,
+ "window_end": task.config.window_end if hasattr(task, 'config') else None,
+ }
+ serialized.append(task_data)
+ except Exception:
+ continue
+
+ history_path.write_text(
+ json.dumps(serialized, ensure_ascii=False, indent=2),
+ encoding="utf-8"
+ )
+ except Exception as e:
+ print(f"保存任务历史失败: {e}")
+
+ def load_task_history(self) -> list:
+ """从文件加载任务历史"""
+ try:
+ history_path = self._get_history_path()
+ if not history_path.exists():
+ return []
+
+ data = json.loads(history_path.read_text(encoding="utf-8"))
+ return data
+ except Exception as e:
+ print(f"加载任务历史失败: {e}")
+ return []
+
+
+# 全局单例
+app_settings = AppSettings()
diff --git a/etl_billiards/gui/utils/cli_builder.py b/etl_billiards/gui/utils/cli_builder.py
new file mode 100644
index 0000000..2e7110e
--- /dev/null
+++ b/etl_billiards/gui/utils/cli_builder.py
@@ -0,0 +1,131 @@
+# -*- coding: utf-8 -*-
+"""CLI 命令构建器"""
+
+from typing import List, Dict, Any, Optional
+from ..models.task_model import TaskConfig
+
+
+# CLI 支持的命令行参数(来自 cli/main.py)
+CLI_SUPPORTED_ARGS = {
+ # 值类型参数
+ "store_id", "tasks", "pg_dsn", "pg_host", "pg_port", "pg_name",
+ "pg_user", "pg_password", "api_base", "api_token", "api_timeout",
+ "api_page_size", "api_retry_max", "window_start", "window_end",
+ "export_root", "log_root", "pipeline_flow", "fetch_root",
+ "ingest_source", "idle_start", "idle_end",
+ # 布尔类型参数
+ "dry_run", "force_window_override", "write_pretty_json", "allow_empty_advance",
+}
+
+
+class CLIBuilder:
+ """构建 CLI 命令行参数"""
+
+ def __init__(self, python_executable: str = "python"):
+ self.python_executable = python_executable
+
+ def build_command(self, config: TaskConfig) -> List[str]:
+ """
+ 根据任务配置构建命令行参数列表
+
+ Args:
+ config: 任务配置对象
+
+ Returns:
+ 命令行参数列表
+ """
+ cmd = [self.python_executable, "-m", "cli.main"]
+
+ # 任务列表
+ if config.tasks:
+ cmd.extend(["--tasks", ",".join(config.tasks)])
+
+ # Pipeline 流程
+ if config.pipeline_flow:
+ cmd.extend(["--pipeline-flow", config.pipeline_flow])
+
+ # Dry-run 模式
+ if config.dry_run:
+ cmd.append("--dry-run")
+
+ # 时间窗口
+ if config.window_start:
+ cmd.extend(["--window-start", config.window_start])
+ if config.window_end:
+ cmd.extend(["--window-end", config.window_end])
+
+ # 数据源目录
+ if config.ingest_source:
+ cmd.extend(["--ingest-source", config.ingest_source])
+
+ # 门店 ID
+ if config.store_id is not None:
+ cmd.extend(["--store-id", str(config.store_id)])
+
+ # 数据库 DSN
+ if config.pg_dsn:
+ cmd.extend(["--pg-dsn", config.pg_dsn])
+
+ # API Token
+ if config.api_token:
+ cmd.extend(["--api-token", config.api_token])
+
+ # 额外参数(只传递 CLI 支持的参数)
+ for key, value in config.extra_args.items():
+ if value is not None and key in CLI_SUPPORTED_ARGS:
+ arg_name = f"--{key.replace('_', '-')}"
+ if isinstance(value, bool):
+ if value:
+ cmd.append(arg_name)
+ else:
+ cmd.extend([arg_name, str(value)])
+
+ return cmd
+
+ def build_command_string(self, config: TaskConfig) -> str:
+ """
+ 构建命令行字符串(用于显示)
+
+ Args:
+ config: 任务配置对象
+
+ Returns:
+ 命令行字符串
+ """
+ cmd = self.build_command(config)
+ # 对包含空格的参数添加引号
+ quoted_cmd = []
+ for arg in cmd:
+ if ' ' in arg or '"' in arg:
+ quoted_cmd.append(f'"{arg}"')
+ else:
+ quoted_cmd.append(arg)
+ return " ".join(quoted_cmd)
+
+ def build_from_dict(self, params: Dict[str, Any]) -> List[str]:
+ """
+ 从字典构建命令行参数
+
+ Args:
+ params: 参数字典
+
+ Returns:
+ 命令行参数列表
+ """
+ config = TaskConfig(
+ tasks=params.get("tasks", []),
+ pipeline_flow=params.get("pipeline_flow", "FULL"),
+ dry_run=params.get("dry_run", False),
+ window_start=params.get("window_start"),
+ window_end=params.get("window_end"),
+ ingest_source=params.get("ingest_source"),
+ store_id=params.get("store_id"),
+ pg_dsn=params.get("pg_dsn"),
+ api_token=params.get("api_token"),
+ extra_args=params.get("extra_args", {}),
+ )
+ return self.build_command(config)
+
+
+# 全局实例
+cli_builder = CLIBuilder()
diff --git a/etl_billiards/gui/utils/config_helper.py b/etl_billiards/gui/utils/config_helper.py
new file mode 100644
index 0000000..4eef080
--- /dev/null
+++ b/etl_billiards/gui/utils/config_helper.py
@@ -0,0 +1,309 @@
+# -*- coding: utf-8 -*-
+"""配置辅助工具"""
+
+import os
+import re
+from pathlib import Path
+from typing import Dict, List, Tuple, Optional, Any
+
+
+# 环境变量分组
+ENV_GROUPS = {
+ "database": {
+ "title": "数据库配置",
+ "keys": ["PG_DSN", "PG_HOST", "PG_PORT", "PG_NAME", "PG_USER", "PG_PASSWORD", "PG_CONNECT_TIMEOUT"],
+ "sensitive": ["PG_PASSWORD"],
+ },
+ "api": {
+ "title": "API 配置",
+ "keys": ["API_BASE", "API_TOKEN", "FICOO_TOKEN", "API_TIMEOUT", "API_PAGE_SIZE", "API_RETRY_MAX"],
+ "sensitive": ["API_TOKEN", "FICOO_TOKEN"],
+ },
+ "store": {
+ "title": "门店配置",
+ "keys": ["STORE_ID", "TIMEZONE", "SCHEMA_OLTP", "SCHEMA_ETL"],
+ "sensitive": [],
+ },
+ "paths": {
+ "title": "路径配置",
+ "keys": ["EXPORT_ROOT", "LOG_ROOT", "FETCH_ROOT", "INGEST_SOURCE_DIR", "JSON_FETCH_ROOT", "JSON_SOURCE_DIR"],
+ "sensitive": [],
+ },
+ "pipeline": {
+ "title": "流水线配置",
+ "keys": ["PIPELINE_FLOW", "RUN_TASKS", "OVERLAP_SECONDS"],
+ "sensitive": [],
+ },
+ "window": {
+ "title": "时间窗口配置",
+ "keys": ["WINDOW_START", "WINDOW_END", "WINDOW_BUSY_MIN", "WINDOW_IDLE_MIN", "IDLE_START", "IDLE_END"],
+ "sensitive": [],
+ },
+ "integrity": {
+ "title": "数据完整性配置",
+ "keys": ["INTEGRITY_MODE", "INTEGRITY_HISTORY_START", "INTEGRITY_HISTORY_END",
+ "INTEGRITY_INCLUDE_DIMENSIONS", "INTEGRITY_AUTO_CHECK", "INTEGRITY_ODS_TASK_CODES"],
+ "sensitive": [],
+ },
+}
+
+
+class ConfigHelper:
+ """配置文件辅助类"""
+
+ def __init__(self, env_path: Optional[Path] = None):
+ """
+ 初始化配置辅助器
+
+ Args:
+ env_path: .env 文件路径,默认使用 AppSettings 中的路径
+ """
+ if env_path is not None:
+ self.env_path = Path(env_path)
+ else:
+ # 从 AppSettings 获取路径
+ from .app_settings import app_settings
+ settings_path = app_settings.env_file_path
+ if settings_path:
+ self.env_path = Path(settings_path)
+ else:
+ # 回退到源码目录
+ self.env_path = Path(__file__).resolve().parents[2] / ".env"
+
+ def load_env(self) -> Dict[str, str]:
+ """
+ 加载 .env 文件内容
+
+ Returns:
+ 环境变量字典
+ """
+ env_vars = {}
+ if not self.env_path.exists():
+ return env_vars
+
+ try:
+ content = self.env_path.read_text(encoding="utf-8", errors="ignore")
+ for line in content.splitlines():
+ parsed = self._parse_line(line)
+ if parsed:
+ key, value = parsed
+ env_vars[key] = value
+ except Exception:
+ pass
+
+ return env_vars
+
+ def save_env(self, env_vars: Dict[str, str]) -> bool:
+ """
+ 保存环境变量到 .env 文件
+
+ Args:
+ env_vars: 环境变量字典
+
+ Returns:
+ 是否保存成功
+ """
+ try:
+ lines = []
+ # 按分组输出
+ written_keys = set()
+
+ for group_id, group_info in ENV_GROUPS.items():
+ group_lines = []
+ for key in group_info["keys"]:
+ if key in env_vars:
+ value = env_vars[key]
+ group_lines.append(self._format_line(key, value))
+ written_keys.add(key)
+
+ if group_lines:
+ lines.append(f"\n# {group_info['title']}")
+ lines.extend(group_lines)
+
+ # 写入未分组的变量
+ other_lines = []
+ for key, value in env_vars.items():
+ if key not in written_keys:
+ other_lines.append(self._format_line(key, value))
+
+ if other_lines:
+ lines.append("\n# 其他配置")
+ lines.extend(other_lines)
+
+ content = "\n".join(lines).strip() + "\n"
+ self.env_path.write_text(content, encoding="utf-8")
+ return True
+ except Exception:
+ return False
+
+ def get_grouped_env(self) -> Dict[str, List[Tuple[str, str, bool]]]:
+ """
+ 获取分组的环境变量
+
+ Returns:
+ 分组字典 {group_id: [(key, value, is_sensitive), ...]}
+ """
+ env_vars = self.load_env()
+ result = {}
+ used_keys = set()
+
+ for group_id, group_info in ENV_GROUPS.items():
+ items = []
+ for key in group_info["keys"]:
+ value = env_vars.get(key, "")
+ is_sensitive = key in group_info.get("sensitive", [])
+ items.append((key, value, is_sensitive))
+ if key in env_vars:
+ used_keys.add(key)
+ result[group_id] = items
+
+ # 添加未分组的变量到 "other" 组
+ other_items = []
+ for key, value in env_vars.items():
+ if key not in used_keys:
+ other_items.append((key, value, False))
+ if other_items:
+ result["other"] = other_items
+
+ return result
+
+ def validate_env(self, env_vars: Dict[str, str]) -> List[str]:
+ """
+ 验证环境变量
+
+ Args:
+ env_vars: 环境变量字典
+
+ Returns:
+ 错误消息列表
+ """
+ errors = []
+
+ # 验证 PG_DSN 格式
+ pg_dsn = env_vars.get("PG_DSN", "")
+ if pg_dsn and not pg_dsn.startswith("postgresql://"):
+ errors.append("PG_DSN 应以 'postgresql://' 开头")
+
+ # 验证端口号
+ pg_port = env_vars.get("PG_PORT", "")
+ if pg_port:
+ try:
+ port = int(pg_port)
+ if port < 1 or port > 65535:
+ errors.append("PG_PORT 应在 1-65535 范围内")
+ except ValueError:
+ errors.append("PG_PORT 应为数字")
+
+ # 验证 STORE_ID
+ store_id = env_vars.get("STORE_ID", "")
+ if store_id:
+ try:
+ int(store_id)
+ except ValueError:
+ errors.append("STORE_ID 应为数字")
+
+ # 验证路径存在性(可选)
+ for key in ["EXPORT_ROOT", "LOG_ROOT", "FETCH_ROOT"]:
+ path = env_vars.get(key, "")
+ if path and not os.path.isabs(path):
+ errors.append(f"{key} 建议使用绝对路径")
+
+ return errors
+
+ def mask_sensitive(self, value: str, visible_chars: int = 4) -> str:
+ """
+ 脱敏敏感值
+
+ Args:
+ value: 原始值
+ visible_chars: 可见字符数
+
+ Returns:
+ 脱敏后的值
+ """
+ if not value or len(value) <= visible_chars:
+ return "*" * len(value) if value else ""
+ return value[:visible_chars] + "*" * (len(value) - visible_chars)
+
+ def _parse_line(self, line: str) -> Optional[Tuple[str, str]]:
+ """解析 .env 文件的一行"""
+ stripped = line.strip()
+ if not stripped or stripped.startswith("#"):
+ return None
+ if stripped.startswith("export "):
+ stripped = stripped[7:].strip()
+ if "=" not in stripped:
+ return None
+
+ key, value = stripped.split("=", 1)
+ key = key.strip()
+ value = self._unquote_value(value)
+ return key, value
+
+ def _unquote_value(self, value: str) -> str:
+ """处理引号和注释"""
+ # 去除内联注释
+ value = self._strip_inline_comment(value)
+ value = value.rstrip(",").strip()
+
+ if not value:
+ return value
+
+ # 去除引号
+ if len(value) >= 2 and value[0] in ("'", '"') and value[-1] == value[0]:
+ return value[1:-1]
+ if len(value) >= 3 and value[0] in ("r", "R") and value[1] in ("'", '"') and value[-1] == value[1]:
+ return value[2:-1]
+
+ return value
+
+ def _strip_inline_comment(self, value: str) -> str:
+ """去除内联注释"""
+ result = []
+ in_quote = False
+ quote_char = ""
+ escape = False
+
+ for ch in value:
+ if escape:
+ result.append(ch)
+ escape = False
+ continue
+ if ch == "\\":
+ escape = True
+ result.append(ch)
+ continue
+ if ch in ("'", '"'):
+ if not in_quote:
+ in_quote = True
+ quote_char = ch
+ elif quote_char == ch:
+ in_quote = False
+ quote_char = ""
+ result.append(ch)
+ continue
+ if ch == "#" and not in_quote:
+ break
+ result.append(ch)
+
+ return "".join(result).rstrip()
+
+ def _format_line(self, key: str, value: str) -> str:
+ """格式化为 .env 行"""
+ # 如果值包含特殊字符,使用引号包裹
+ if any(c in value for c in [' ', '"', "'", '#', '\n', '\r']):
+ # 使用双引号,转义内部的双引号
+ escaped = value.replace('\\', '\\\\').replace('"', '\\"')
+ return f'{key}="{escaped}"'
+ return f"{key}={value}"
+
+ @staticmethod
+ def get_group_title(group_id: str) -> str:
+ """获取分组标题"""
+ if group_id in ENV_GROUPS:
+ return ENV_GROUPS[group_id]["title"]
+ return "其他配置"
+
+
+# 全局实例
+config_helper = ConfigHelper()
diff --git a/etl_billiards/gui/widgets/__init__.py b/etl_billiards/gui/widgets/__init__.py
new file mode 100644
index 0000000..5d20561
--- /dev/null
+++ b/etl_billiards/gui/widgets/__init__.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+"""GUI 组件模块"""
+
+from .task_panel import TaskPanel
+from .env_editor import EnvEditor
+from .log_viewer import LogViewer
+from .db_viewer import DBViewer
+from .status_panel import StatusPanel
+from .task_manager import TaskManager
+
+__all__ = [
+ "TaskPanel",
+ "EnvEditor",
+ "LogViewer",
+ "DBViewer",
+ "StatusPanel",
+ "TaskManager",
+]
diff --git a/etl_billiards/gui/widgets/db_viewer.py b/etl_billiards/gui/widgets/db_viewer.py
new file mode 100644
index 0000000..d0b4909
--- /dev/null
+++ b/etl_billiards/gui/widgets/db_viewer.py
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+"""数据库查看器"""
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QSplitter,
+ QGroupBox, QLabel, QPushButton, QLineEdit, QPlainTextEdit,
+ QTableWidget, QTableWidgetItem, QTreeWidget, QTreeWidgetItem,
+ QHeaderView, QComboBox, QTabWidget, QMessageBox, QFrame
+)
+from PySide6.QtCore import Qt, Signal
+from PySide6.QtGui import QFont
+
+from ..workers.db_worker import DBWorker
+from ..utils.config_helper import ConfigHelper
+
+
+# 常用查询模板
+QUERY_TEMPLATES = {
+ "ODS 行数统计": """
+SELECT
+ table_name,
+ (xpath('/row/cnt/text()',
+ query_to_xml('SELECT COUNT(*) AS cnt FROM ' || table_schema || '.' || table_name, false, false, ''))
+ )[1]::text::bigint AS row_count
+FROM information_schema.tables
+WHERE table_schema = 'billiards_ods'
+ORDER BY table_name;
+""",
+ "DWD 行数统计": """
+SELECT
+ table_name,
+ (xpath('/row/cnt/text()',
+ query_to_xml('SELECT COUNT(*) AS cnt FROM ' || table_schema || '.' || table_name, false, false, ''))
+ )[1]::text::bigint AS row_count
+FROM information_schema.tables
+WHERE table_schema = 'billiards_dwd'
+ORDER BY table_name;
+""",
+ "ETL 游标状态": """
+SELECT
+ task_code,
+ last_start,
+ last_end,
+ last_run_id,
+ updated_at
+FROM etl_admin.etl_cursor
+ORDER BY task_code;
+""",
+ "最近运行记录": """
+SELECT
+ run_id,
+ task_code,
+ status,
+ started_at,
+ finished_at,
+ EXTRACT(EPOCH FROM (finished_at - started_at))::int AS duration_sec,
+ rows_affected
+FROM etl_admin.run_tracker
+ORDER BY started_at DESC
+LIMIT 50;
+""",
+ "ODS 最新入库时间": """
+SELECT
+ 'payment_transactions' AS table_name, MAX(fetched_at) AS max_fetched_at FROM billiards_ods.payment_transactions
+UNION ALL
+SELECT 'member_profiles', MAX(fetched_at) FROM billiards_ods.member_profiles
+UNION ALL
+SELECT 'settlement_records', MAX(fetched_at) FROM billiards_ods.settlement_records
+UNION ALL
+SELECT 'recharge_settlements', MAX(fetched_at) FROM billiards_ods.recharge_settlements
+ORDER BY table_name;
+""",
+}
+
+
+class DBViewer(QWidget):
+ """数据库查看器"""
+
+ # 信号
+ connection_changed = Signal(bool, str) # 连接状态变化
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.config_helper = ConfigHelper()
+ self.db_worker = DBWorker(self)
+ self._connected = False
+
+ self._init_ui()
+ self._connect_signals()
+ self._load_dsn_from_env()
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(16)
+
+ # 标题
+ title = QLabel("数据库查看器")
+ title.setProperty("heading", True)
+ layout.addWidget(title)
+
+ # 连接配置
+ conn_group = QGroupBox("数据库连接")
+ conn_layout = QHBoxLayout(conn_group)
+
+ conn_layout.addWidget(QLabel("DSN:"))
+ self.dsn_edit = QLineEdit()
+ self.dsn_edit.setPlaceholderText("postgresql://user:password@host:5432/dbname")
+ self.dsn_edit.setEchoMode(QLineEdit.Password)
+ conn_layout.addWidget(self.dsn_edit, 1)
+
+ self.show_dsn_btn = QPushButton("显示")
+ self.show_dsn_btn.setProperty("secondary", True)
+ self.show_dsn_btn.setCheckable(True)
+ self.show_dsn_btn.setFixedWidth(60)
+ conn_layout.addWidget(self.show_dsn_btn)
+
+ self.connect_btn = QPushButton("连接")
+ self.connect_btn.setFixedWidth(80)
+ conn_layout.addWidget(self.connect_btn)
+
+ self.disconnect_btn = QPushButton("断开")
+ self.disconnect_btn.setProperty("secondary", True)
+ self.disconnect_btn.setFixedWidth(80)
+ self.disconnect_btn.setEnabled(False)
+ conn_layout.addWidget(self.disconnect_btn)
+
+ layout.addWidget(conn_group)
+
+ # 主分割器
+ main_splitter = QSplitter(Qt.Horizontal)
+ layout.addWidget(main_splitter, 1)
+
+ # 左侧:表浏览器
+ left_widget = self._create_table_browser()
+ main_splitter.addWidget(left_widget)
+
+ # 右侧:查询和结果
+ right_widget = self._create_query_area()
+ main_splitter.addWidget(right_widget)
+
+ # 设置分割比例
+ main_splitter.setSizes([300, 700])
+
+ def _create_table_browser(self) -> QWidget:
+ """创建表浏览器"""
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(0, 0, 8, 0)
+
+ # 标题和刷新按钮
+ header_layout = QHBoxLayout()
+ header_layout.addWidget(QLabel("表结构"))
+ self.refresh_tables_btn = QPushButton("刷新")
+ self.refresh_tables_btn.setProperty("secondary", True)
+ self.refresh_tables_btn.setEnabled(False)
+ header_layout.addWidget(self.refresh_tables_btn)
+ layout.addLayout(header_layout)
+
+ # 表树形视图
+ self.table_tree = QTreeWidget()
+ self.table_tree.setHeaderLabels(["名称", "行数", "最后更新"])
+ self.table_tree.header().setSectionResizeMode(0, QHeaderView.Stretch)
+ self.table_tree.setColumnWidth(1, 80)
+ self.table_tree.setColumnWidth(2, 130)
+ layout.addWidget(self.table_tree, 1)
+
+ return widget
+
+ def _create_query_area(self) -> QWidget:
+ """创建查询区域"""
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(8, 0, 0, 0)
+
+ # 查询输入区
+ query_group = QGroupBox("SQL 查询")
+ query_layout = QVBoxLayout(query_group)
+
+ # 模板选择
+ template_layout = QHBoxLayout()
+ template_layout.addWidget(QLabel("常用查询:"))
+ self.template_combo = QComboBox()
+ self.template_combo.addItem("-- 选择模板 --")
+ for name in QUERY_TEMPLATES.keys():
+ self.template_combo.addItem(name)
+ template_layout.addWidget(self.template_combo, 1)
+ query_layout.addLayout(template_layout)
+
+ # SQL 编辑器
+ self.sql_editor = QPlainTextEdit()
+ self.sql_editor.setObjectName("sqlEditor")
+ self.sql_editor.setPlaceholderText("输入 SQL 查询语句...")
+ self.sql_editor.setFont(QFont("Consolas", 11))
+ self.sql_editor.setMaximumHeight(150)
+ query_layout.addWidget(self.sql_editor)
+
+ # 执行按钮
+ exec_layout = QHBoxLayout()
+ exec_layout.addStretch()
+
+ self.exec_btn = QPushButton("执行查询 (Ctrl+Enter)")
+ self.exec_btn.setEnabled(False)
+ exec_layout.addWidget(self.exec_btn)
+
+ query_layout.addLayout(exec_layout)
+ layout.addWidget(query_group)
+
+ # 结果区域
+ result_group = QGroupBox("查询结果")
+ result_layout = QVBoxLayout(result_group)
+
+ # 结果表格
+ self.result_table = QTableWidget()
+ self.result_table.setAlternatingRowColors(True)
+ self.result_table.horizontalHeader().setStretchLastSection(True)
+ result_layout.addWidget(self.result_table, 1)
+
+ # 结果统计
+ self.result_label = QLabel("就绪")
+ self.result_label.setProperty("subheading", True)
+ result_layout.addWidget(self.result_label)
+
+ layout.addWidget(result_group, 1)
+
+ return widget
+
+ def _connect_signals(self):
+ """连接信号"""
+ # 连接按钮
+ self.show_dsn_btn.toggled.connect(self._toggle_dsn_visibility)
+ self.connect_btn.clicked.connect(self._connect_db)
+ self.disconnect_btn.clicked.connect(self._disconnect_db)
+ self.refresh_tables_btn.clicked.connect(self._refresh_tables)
+
+ # 模板选择
+ self.template_combo.currentIndexChanged.connect(self._on_template_selected)
+
+ # 执行查询
+ self.exec_btn.clicked.connect(self._execute_query)
+
+ # 表双击
+ self.table_tree.itemDoubleClicked.connect(self._on_table_double_clicked)
+
+ # 工作线程信号
+ self.db_worker.connection_status.connect(self._on_connection_status)
+ self.db_worker.tables_loaded.connect(self._on_tables_loaded)
+ self.db_worker.query_finished.connect(self._on_query_finished)
+ self.db_worker.query_error.connect(self._on_query_error)
+
+ def _load_dsn_from_env(self):
+ """从环境变量加载 DSN"""
+ env_vars = self.config_helper.load_env()
+ dsn = env_vars.get("PG_DSN", "")
+ if dsn:
+ self.dsn_edit.setText(dsn)
+
+ def _toggle_dsn_visibility(self, checked: bool):
+ """切换 DSN 可见性"""
+ self.dsn_edit.setEchoMode(
+ QLineEdit.Normal if checked else QLineEdit.Password
+ )
+ self.show_dsn_btn.setText("隐藏" if checked else "显示")
+
+ def _connect_db(self):
+ """连接数据库"""
+ dsn = self.dsn_edit.text().strip()
+ if not dsn:
+ QMessageBox.warning(self, "提示", "请输入数据库连接字符串")
+ return
+
+ self.connect_btn.setEnabled(False)
+ self.connect_btn.setText("连接中...")
+ self.db_worker.connect_db(dsn)
+
+ def _disconnect_db(self):
+ """断开数据库连接"""
+ self.db_worker.disconnect_db()
+
+ def _refresh_tables(self):
+ """刷新表列表"""
+ self.db_worker.load_tables()
+
+ def _on_connection_status(self, connected: bool, message: str):
+ """处理连接状态变化"""
+ self._connected = connected
+ self.connect_btn.setEnabled(not connected)
+ self.connect_btn.setText("连接")
+ self.disconnect_btn.setEnabled(connected)
+ self.refresh_tables_btn.setEnabled(connected)
+ self.exec_btn.setEnabled(connected)
+
+ self.connection_changed.emit(connected, message)
+
+ if connected:
+ # 自动加载表列表
+ self._refresh_tables()
+
+ def _on_tables_loaded(self, tables_dict: dict):
+ """处理表列表加载完成"""
+ self.table_tree.clear()
+
+ for schema, tables in tables_dict.items():
+ schema_item = QTreeWidgetItem([schema, "", ""])
+ schema_item.setExpanded(True)
+
+ for table_name, row_count, updated_at in tables:
+ table_item = QTreeWidgetItem([table_name, str(row_count), updated_at])
+ table_item.setData(0, Qt.UserRole, f"{schema}.{table_name}")
+ schema_item.addChild(table_item)
+
+ self.table_tree.addTopLevelItem(schema_item)
+
+ def _on_template_selected(self, index: int):
+ """模板选择变化"""
+ if index <= 0:
+ return
+
+ template_name = self.template_combo.currentText()
+ if template_name in QUERY_TEMPLATES:
+ self.sql_editor.setPlainText(QUERY_TEMPLATES[template_name].strip())
+
+ # 重置选择
+ self.template_combo.setCurrentIndex(0)
+
+ def _on_table_double_clicked(self, item: QTreeWidgetItem, column: int):
+ """表双击事件"""
+ full_name = item.data(0, Qt.UserRole)
+ if full_name:
+ # 生成预览查询
+ sql = f"SELECT * FROM {full_name} LIMIT 100;"
+ self.sql_editor.setPlainText(sql)
+ self._execute_query()
+
+ def _execute_query(self):
+ """执行查询"""
+ sql = self.sql_editor.toPlainText().strip()
+ if not sql:
+ QMessageBox.warning(self, "提示", "请输入 SQL 语句")
+ return
+
+ self.exec_btn.setEnabled(False)
+ self.exec_btn.setText("执行中...")
+ self.result_label.setText("正在查询...")
+
+ self.db_worker.execute_query(sql)
+
+ def _on_query_finished(self, columns: list, rows: list):
+ """查询完成"""
+ self.exec_btn.setEnabled(True)
+ self.exec_btn.setText("执行查询 (Ctrl+Enter)")
+
+ # 更新结果表格
+ self.result_table.clear()
+ self.result_table.setColumnCount(len(columns))
+ self.result_table.setRowCount(len(rows))
+ self.result_table.setHorizontalHeaderLabels(columns)
+
+ for row_idx, row_data in enumerate(rows):
+ for col_idx, col_name in enumerate(columns):
+ value = row_data.get(col_name, "")
+ item = QTableWidgetItem(str(value) if value is not None else "NULL")
+ if value is None:
+ item.setForeground(Qt.gray)
+ self.result_table.setItem(row_idx, col_idx, item)
+
+ # 更新统计
+ self.result_label.setText(f"返回 {len(rows)} 行, {len(columns)} 列")
+
+ def _on_query_error(self, error: str):
+ """查询错误"""
+ self.exec_btn.setEnabled(True)
+ self.exec_btn.setText("执行查询 (Ctrl+Enter)")
+ self.result_label.setText(f"错误: {error}")
+ QMessageBox.critical(self, "查询错误", error)
+
+ def close_connection(self):
+ """关闭连接"""
+ if self._connected:
+ self.db_worker.disconnect_db()
+
+ def keyPressEvent(self, event):
+ """键盘事件"""
+ # Ctrl+Enter 执行查询
+ if event.modifiers() == Qt.ControlModifier and event.key() == Qt.Key_Return:
+ if self._connected:
+ self._execute_query()
+ else:
+ super().keyPressEvent(event)
diff --git a/etl_billiards/gui/widgets/env_editor.py b/etl_billiards/gui/widgets/env_editor.py
new file mode 100644
index 0000000..d27ce23
--- /dev/null
+++ b/etl_billiards/gui/widgets/env_editor.py
@@ -0,0 +1,318 @@
+# -*- coding: utf-8 -*-
+"""环境变量编辑器"""
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
+ QGroupBox, QLabel, QLineEdit, QPushButton, QScrollArea,
+ QFrame, QMessageBox, QFileDialog, QCheckBox
+)
+from PySide6.QtCore import Qt, Signal
+
+from ..utils.config_helper import ConfigHelper, ENV_GROUPS
+
+
+class EnvEditor(QWidget):
+ """环境变量编辑器"""
+
+ # 信号
+ config_saved = Signal() # 配置保存成功
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.config_helper = ConfigHelper()
+ self.field_widgets = {} # 存储字段控件
+ self.show_sensitive = False
+
+ self._init_ui()
+ self.load_config()
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(16)
+
+ # 标题和按钮
+ header_layout = QHBoxLayout()
+
+ title = QLabel("环境配置")
+ title.setProperty("heading", True)
+ header_layout.addWidget(title)
+
+ header_layout.addStretch()
+
+ self.show_sensitive_check = QCheckBox("显示敏感信息")
+ self.show_sensitive_check.stateChanged.connect(self._toggle_sensitive)
+ header_layout.addWidget(self.show_sensitive_check)
+
+ self.import_btn = QPushButton("导入")
+ self.import_btn.setProperty("secondary", True)
+ self.import_btn.clicked.connect(self._import_config)
+ header_layout.addWidget(self.import_btn)
+
+ self.export_btn = QPushButton("导出")
+ self.export_btn.setProperty("secondary", True)
+ self.export_btn.clicked.connect(self._export_config)
+ header_layout.addWidget(self.export_btn)
+
+ self.reload_btn = QPushButton("重新加载")
+ self.reload_btn.setProperty("secondary", True)
+ self.reload_btn.clicked.connect(self.load_config)
+ header_layout.addWidget(self.reload_btn)
+
+ self.save_btn = QPushButton("保存")
+ self.save_btn.clicked.connect(self._save_config)
+ header_layout.addWidget(self.save_btn)
+
+ layout.addLayout(header_layout)
+
+ # 配置文件路径
+ path_layout = QHBoxLayout()
+ path_layout.addWidget(QLabel("配置文件:"))
+ self.path_label = QLabel(str(self.config_helper.env_path))
+ self.path_label.setProperty("subheading", True)
+ path_layout.addWidget(self.path_label, 1)
+ layout.addLayout(path_layout)
+
+ # 滚动区域
+ scroll_area = QScrollArea()
+ scroll_area.setWidgetResizable(True)
+ scroll_area.setFrameShape(QFrame.NoFrame)
+ layout.addWidget(scroll_area, 1)
+
+ # 配置组容器
+ config_widget = QWidget()
+ self.config_layout = QVBoxLayout(config_widget)
+ self.config_layout.setSpacing(16)
+
+ # 创建各配置组
+ self._create_config_groups()
+
+ # 弹性空间
+ self.config_layout.addStretch()
+
+ scroll_area.setWidget(config_widget)
+
+ # 验证结果
+ self.validation_label = QLabel()
+ self.validation_label.setWordWrap(True)
+ layout.addWidget(self.validation_label)
+
+ def _create_config_groups(self):
+ """创建配置分组"""
+ for group_id, group_info in ENV_GROUPS.items():
+ group = QGroupBox(group_info["title"])
+ grid_layout = QGridLayout(group)
+
+ for row, key in enumerate(group_info["keys"]):
+ # 标签
+ label = QLabel(f"{key}:")
+ label.setMinimumWidth(180)
+ grid_layout.addWidget(label, row, 0)
+
+ # 输入框
+ edit = QLineEdit()
+ edit.setPlaceholderText(self._get_placeholder(key))
+
+ # 敏感字段处理
+ if key in group_info.get("sensitive", []):
+ edit.setEchoMode(QLineEdit.Password)
+ edit.setProperty("sensitive", True)
+
+ edit.textChanged.connect(self._on_value_changed)
+ grid_layout.addWidget(edit, row, 1)
+
+ # 存储控件引用
+ self.field_widgets[key] = edit
+
+ self.config_layout.addWidget(group)
+
+ # 其他配置组(动态添加)
+ self.other_group = QGroupBox("其他配置")
+ self.other_layout = QGridLayout(self.other_group)
+ self.other_group.setVisible(False)
+ self.config_layout.addWidget(self.other_group)
+
+ def load_config(self):
+ """加载配置"""
+ env_vars = self.config_helper.load_env()
+
+ # 更新已知字段
+ for key, edit in self.field_widgets.items():
+ value = env_vars.get(key, "")
+ edit.blockSignals(True)
+ edit.setText(value)
+ edit.blockSignals(False)
+
+ # 处理其他字段
+ known_keys = set(self.field_widgets.keys())
+ other_keys = [k for k in env_vars.keys() if k not in known_keys]
+
+ # 清除旧的其他字段
+ while self.other_layout.count():
+ item = self.other_layout.takeAt(0)
+ if item.widget():
+ item.widget().deleteLater()
+
+ # 添加其他字段
+ if other_keys:
+ self.other_group.setVisible(True)
+ for row, key in enumerate(sorted(other_keys)):
+ label = QLabel(f"{key}:")
+ self.other_layout.addWidget(label, row, 0)
+
+ edit = QLineEdit(env_vars[key])
+ edit.textChanged.connect(self._on_value_changed)
+ self.other_layout.addWidget(edit, row, 1)
+
+ self.field_widgets[key] = edit
+ else:
+ self.other_group.setVisible(False)
+
+ self._validate()
+
+ def _save_config(self):
+ """保存配置"""
+ # 收集所有值
+ env_vars = {}
+ for key, edit in self.field_widgets.items():
+ value = edit.text().strip()
+ if value:
+ env_vars[key] = value
+
+ # 验证
+ errors = self.config_helper.validate_env(env_vars)
+ if errors:
+ reply = QMessageBox.question(
+ self,
+ "验证警告",
+ "配置存在以下问题:\n\n" + "\n".join(f"• {e}" for e in errors) + "\n\n是否仍要保存?",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.No
+ )
+ if reply == QMessageBox.No:
+ return
+
+ # 保存
+ if self.config_helper.save_env(env_vars):
+ QMessageBox.information(self, "成功", "配置已保存")
+ self.config_saved.emit()
+ else:
+ QMessageBox.critical(self, "错误", "保存配置失败")
+
+ def _import_config(self):
+ """导入配置"""
+ file_path, _ = QFileDialog.getOpenFileName(
+ self,
+ "导入配置文件",
+ "",
+ "环境文件 (*.env);;所有文件 (*.*)"
+ )
+ if not file_path:
+ return
+
+ try:
+ from pathlib import Path
+ temp_helper = ConfigHelper(Path(file_path))
+ env_vars = temp_helper.load_env()
+
+ # 更新字段
+ for key, value in env_vars.items():
+ if key in self.field_widgets:
+ self.field_widgets[key].setText(value)
+
+ QMessageBox.information(self, "成功", f"已导入 {len(env_vars)} 个配置项")
+ except Exception as e:
+ QMessageBox.critical(self, "错误", f"导入失败: {e}")
+
+ def _export_config(self):
+ """导出配置"""
+ file_path, _ = QFileDialog.getSaveFileName(
+ self,
+ "导出配置文件",
+ ".env.backup",
+ "环境文件 (*.env);;所有文件 (*.*)"
+ )
+ if not file_path:
+ return
+
+ try:
+ from pathlib import Path
+
+ # 收集当前值
+ env_vars = {}
+ for key, edit in self.field_widgets.items():
+ value = edit.text().strip()
+ if value:
+ env_vars[key] = value
+
+ # 保存到指定路径
+ temp_helper = ConfigHelper(Path(file_path))
+ if temp_helper.save_env(env_vars):
+ QMessageBox.information(self, "成功", f"配置已导出到:\n{file_path}")
+ else:
+ QMessageBox.critical(self, "错误", "导出失败")
+ except Exception as e:
+ QMessageBox.critical(self, "错误", f"导出失败: {e}")
+
+ def _toggle_sensitive(self, state: int):
+ """切换敏感信息显示"""
+ self.show_sensitive = state == Qt.Checked
+
+ for key, edit in self.field_widgets.items():
+ if edit.property("sensitive"):
+ edit.setEchoMode(
+ QLineEdit.Normal if self.show_sensitive else QLineEdit.Password
+ )
+
+ def _on_value_changed(self):
+ """值变化时验证"""
+ self._validate()
+
+ def _validate(self):
+ """验证配置"""
+ env_vars = {}
+ for key, edit in self.field_widgets.items():
+ value = edit.text().strip()
+ if value:
+ env_vars[key] = value
+
+ errors = self.config_helper.validate_env(env_vars)
+
+ if errors:
+ self.validation_label.setText("⚠ " + "; ".join(errors))
+ self.validation_label.setProperty("status", "warning")
+ else:
+ self.validation_label.setText("✓ 配置验证通过")
+ self.validation_label.setProperty("status", "success")
+
+ self.validation_label.style().unpolish(self.validation_label)
+ self.validation_label.style().polish(self.validation_label)
+
+ @staticmethod
+ def _get_placeholder(key: str) -> str:
+ """获取占位符提示"""
+ placeholders = {
+ "PG_DSN": "postgresql://user:password@host:5432/dbname",
+ "PG_HOST": "localhost",
+ "PG_PORT": "5432",
+ "PG_NAME": "billiards",
+ "PG_USER": "postgres",
+ "PG_PASSWORD": "密码",
+ "API_BASE": "https://pc.ficoo.vip/apiprod/admin/v1",
+ "API_TOKEN": "Bearer token",
+ "API_TIMEOUT": "20",
+ "API_PAGE_SIZE": "200",
+ "STORE_ID": "门店ID (数字)",
+ "TIMEZONE": "Asia/Taipei",
+ "EXPORT_ROOT": "export/JSON",
+ "LOG_ROOT": "export/LOG",
+ "FETCH_ROOT": "JSON 抓取输出目录",
+ "INGEST_SOURCE_DIR": "本地 JSON 输入目录",
+ "PIPELINE_FLOW": "FULL / FETCH_ONLY / INGEST_ONLY",
+ "RUN_TASKS": "任务列表,逗号分隔",
+ "OVERLAP_SECONDS": "3600",
+ "WINDOW_START": "2025-07-01 00:00:00",
+ "WINDOW_END": "2025-08-01 00:00:00",
+ }
+ return placeholders.get(key, "")
diff --git a/etl_billiards/gui/widgets/log_viewer.py b/etl_billiards/gui/widgets/log_viewer.py
new file mode 100644
index 0000000..3172468
--- /dev/null
+++ b/etl_billiards/gui/widgets/log_viewer.py
@@ -0,0 +1,247 @@
+# -*- coding: utf-8 -*-
+"""日志查看器"""
+
+import re
+from datetime import datetime
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout,
+ QPlainTextEdit, QPushButton, QLineEdit, QLabel,
+ QComboBox, QCheckBox, QFileDialog, QMessageBox
+)
+from PySide6.QtCore import Qt, Signal, Slot
+from PySide6.QtGui import QTextCharFormat, QColor, QFont, QTextCursor
+
+
+class LogViewer(QWidget):
+ """日志查看器"""
+
+ # 信号
+ log_cleared = Signal()
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.max_lines = 10000
+ self.auto_scroll = True
+ self.filter_text = ""
+ self.filter_level = "ALL"
+ self._all_logs = [] # 存储所有日志
+
+ self._init_ui()
+ self._connect_signals()
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(8)
+
+ # 标题和工具栏
+ header_layout = QHBoxLayout()
+
+ title = QLabel("执行日志")
+ title.setProperty("heading", True)
+ header_layout.addWidget(title)
+
+ header_layout.addStretch()
+
+ # 日志级别过滤
+ header_layout.addWidget(QLabel("级别:"))
+ self.level_combo = QComboBox()
+ self.level_combo.addItems(["ALL", "INFO", "WARNING", "ERROR", "DEBUG"])
+ self.level_combo.setFixedWidth(100)
+ header_layout.addWidget(self.level_combo)
+
+ # 搜索框
+ header_layout.addWidget(QLabel("搜索:"))
+ self.search_edit = QLineEdit()
+ self.search_edit.setPlaceholderText("输入关键字...")
+ self.search_edit.setFixedWidth(200)
+ header_layout.addWidget(self.search_edit)
+
+ # 自动滚动
+ self.auto_scroll_check = QCheckBox("自动滚动")
+ self.auto_scroll_check.setChecked(True)
+ header_layout.addWidget(self.auto_scroll_check)
+
+ layout.addLayout(header_layout)
+
+ # 日志文本区域
+ self.log_text = QPlainTextEdit()
+ self.log_text.setObjectName("logViewer")
+ self.log_text.setReadOnly(True)
+ self.log_text.setFont(QFont("Consolas", 10))
+ self.log_text.setLineWrapMode(QPlainTextEdit.NoWrap)
+ layout.addWidget(self.log_text, 1)
+
+ # 底部工具栏
+ footer_layout = QHBoxLayout()
+
+ self.line_count_label = QLabel("0 行")
+ self.line_count_label.setProperty("subheading", True)
+ footer_layout.addWidget(self.line_count_label)
+
+ footer_layout.addStretch()
+
+ self.copy_btn = QPushButton("复制全部")
+ self.copy_btn.setProperty("secondary", True)
+ footer_layout.addWidget(self.copy_btn)
+
+ self.export_btn = QPushButton("导出")
+ self.export_btn.setProperty("secondary", True)
+ footer_layout.addWidget(self.export_btn)
+
+ self.clear_btn = QPushButton("清空")
+ self.clear_btn.setProperty("secondary", True)
+ footer_layout.addWidget(self.clear_btn)
+
+ layout.addLayout(footer_layout)
+
+ def _connect_signals(self):
+ """连接信号"""
+ self.level_combo.currentTextChanged.connect(self._apply_filter)
+ self.search_edit.textChanged.connect(self._apply_filter)
+ self.auto_scroll_check.stateChanged.connect(self._toggle_auto_scroll)
+ self.copy_btn.clicked.connect(self._copy_all)
+ self.export_btn.clicked.connect(self._export_log)
+ self.clear_btn.clicked.connect(self._clear_log)
+
+ @Slot(str)
+ def append_log(self, text: str):
+ """追加日志"""
+ # 添加时间戳(如果没有)
+ if not re.match(r'^\d{4}-\d{2}-\d{2}', text) and not text.startswith('['):
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ text = f"[{timestamp}] {text}"
+
+ # 存储到全部日志
+ self._all_logs.append(text)
+
+ # 限制日志行数
+ if len(self._all_logs) > self.max_lines:
+ self._all_logs = self._all_logs[-self.max_lines:]
+
+ # 检查是否通过过滤器
+ if self._matches_filter(text):
+ self._append_formatted_line(text)
+
+ # 更新行数
+ self._update_line_count()
+
+ def _append_formatted_line(self, text: str):
+ """追加格式化的行"""
+ cursor = self.log_text.textCursor()
+ cursor.movePosition(QTextCursor.End)
+
+ # 设置格式
+ fmt = QTextCharFormat()
+
+ text_lower = text.lower()
+ if "[error]" in text_lower or "错误" in text or "失败" in text:
+ fmt.setForeground(QColor("#d93025"))
+ fmt.setFontWeight(QFont.Bold)
+ elif "[warning]" in text_lower or "警告" in text or "warn" in text_lower:
+ fmt.setForeground(QColor("#f9ab00"))
+ elif "[info]" in text_lower:
+ fmt.setForeground(QColor("#1a73e8"))
+ elif "[debug]" in text_lower:
+ fmt.setForeground(QColor("#9aa0a6"))
+ elif "[gui]" in text_lower:
+ fmt.setForeground(QColor("#1e8e3e"))
+ else:
+ fmt.setForeground(QColor("#333333"))
+
+ cursor.insertText(text + "\n", fmt)
+
+ # 自动滚动
+ if self.auto_scroll:
+ self.log_text.verticalScrollBar().setValue(
+ self.log_text.verticalScrollBar().maximum()
+ )
+
+ def _matches_filter(self, text: str) -> bool:
+ """检查是否匹配过滤器"""
+ # 级别过滤
+ if self.filter_level != "ALL":
+ level_marker = f"[{self.filter_level}]"
+ if level_marker.lower() not in text.lower():
+ return False
+
+ # 文本过滤
+ if self.filter_text:
+ if self.filter_text.lower() not in text.lower():
+ return False
+
+ return True
+
+ def _apply_filter(self):
+ """应用过滤器"""
+ self.filter_level = self.level_combo.currentText()
+ self.filter_text = self.search_edit.text().strip()
+
+ # 重新显示日志
+ self.log_text.clear()
+ for line in self._all_logs:
+ if self._matches_filter(line):
+ self._append_formatted_line(line)
+
+ self._update_line_count()
+
+ def _toggle_auto_scroll(self, state: int):
+ """切换自动滚动"""
+ self.auto_scroll = state == Qt.Checked
+
+ def _copy_all(self):
+ """复制全部日志"""
+ from PySide6.QtWidgets import QApplication
+ text = self.log_text.toPlainText()
+ QApplication.clipboard().setText(text)
+ QMessageBox.information(self, "提示", "日志已复制到剪贴板")
+
+ def _export_log(self):
+ """导出日志"""
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+ default_name = f"etl_log_{timestamp}.txt"
+
+ file_path, _ = QFileDialog.getSaveFileName(
+ self,
+ "导出日志",
+ default_name,
+ "文本文件 (*.txt);;日志文件 (*.log);;所有文件 (*.*)"
+ )
+
+ if not file_path:
+ return
+
+ try:
+ with open(file_path, "w", encoding="utf-8") as f:
+ f.write(self.log_text.toPlainText())
+ QMessageBox.information(self, "成功", f"日志已导出到:\n{file_path}")
+ except Exception as e:
+ QMessageBox.critical(self, "错误", f"导出失败: {e}")
+
+ def _clear_log(self):
+ """清空日志"""
+ reply = QMessageBox.question(
+ self,
+ "确认",
+ "确定要清空所有日志吗?",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.No
+ )
+
+ if reply == QMessageBox.Yes:
+ self._all_logs.clear()
+ self.log_text.clear()
+ self._update_line_count()
+ self.log_cleared.emit()
+
+ def _update_line_count(self):
+ """更新行数显示"""
+ visible_count = self.log_text.document().blockCount() - 1
+ total_count = len(self._all_logs)
+
+ if visible_count < total_count:
+ self.line_count_label.setText(f"{visible_count} / {total_count} 行")
+ else:
+ self.line_count_label.setText(f"{total_count} 行")
diff --git a/etl_billiards/gui/widgets/settings_dialog.py b/etl_billiards/gui/widgets/settings_dialog.py
new file mode 100644
index 0000000..1d6a47a
--- /dev/null
+++ b/etl_billiards/gui/widgets/settings_dialog.py
@@ -0,0 +1,166 @@
+# -*- coding: utf-8 -*-
+"""应用程序设置对话框"""
+
+from pathlib import Path
+
+from PySide6.QtWidgets import (
+ QDialog, QVBoxLayout, QHBoxLayout, QGridLayout,
+ QGroupBox, QLabel, QLineEdit, QPushButton,
+ QFileDialog, QMessageBox, QDialogButtonBox
+)
+from PySide6.QtCore import Qt
+
+from ..utils.app_settings import app_settings
+
+
+class SettingsDialog(QDialog):
+ """设置对话框"""
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.setWindowTitle("应用程序设置")
+ self.setMinimumWidth(600)
+ self._init_ui()
+ self._load_settings()
+
+ def _init_ui(self):
+ layout = QVBoxLayout(self)
+
+ # ETL 项目路径
+ project_group = QGroupBox("ETL 项目配置")
+ project_layout = QGridLayout(project_group)
+
+ project_layout.addWidget(QLabel("ETL 项目路径:"), 0, 0)
+ self.project_path_edit = QLineEdit()
+ self.project_path_edit.setPlaceholderText("例: etl_billiards")
+ project_layout.addWidget(self.project_path_edit, 0, 1)
+
+ browse_project_btn = QPushButton("浏览...")
+ browse_project_btn.clicked.connect(self._browse_project_path)
+ project_layout.addWidget(browse_project_btn, 0, 2)
+
+ project_layout.addWidget(QLabel(".env 文件路径:"), 1, 0)
+ self.env_path_edit = QLineEdit()
+ self.env_path_edit.setPlaceholderText("例: etl_billiards/.env")
+ project_layout.addWidget(self.env_path_edit, 1, 1)
+
+ browse_env_btn = QPushButton("浏览...")
+ browse_env_btn.clicked.connect(self._browse_env_path)
+ project_layout.addWidget(browse_env_btn, 1, 2)
+
+ # 验证按钮
+ validate_btn = QPushButton("验证配置")
+ validate_btn.clicked.connect(self._validate_config)
+ project_layout.addWidget(validate_btn, 2, 1)
+
+ # 验证结果
+ self.validation_label = QLabel()
+ self.validation_label.setWordWrap(True)
+ project_layout.addWidget(self.validation_label, 3, 0, 1, 3)
+
+ layout.addWidget(project_group)
+
+ # 说明
+ note = QLabel(
+ "说明:\n"
+ "• ETL 项目路径:包含 cli/main.py 的目录\n"
+ "• .env 文件路径:环境变量配置文件\n"
+ "• 配置后才能正常执行 ETL 任务"
+ )
+ note.setProperty("subheading", True)
+ note.setWordWrap(True)
+ layout.addWidget(note)
+
+ layout.addStretch()
+
+ # 按钮
+ btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+ btn_box.accepted.connect(self._save_and_accept)
+ btn_box.rejected.connect(self.reject)
+ layout.addWidget(btn_box)
+
+ def _load_settings(self):
+ """加载设置"""
+ self.project_path_edit.setText(app_settings.etl_project_path)
+ self.env_path_edit.setText(app_settings.env_file_path)
+ self._validate_config()
+
+ def _browse_project_path(self):
+ """浏览项目路径"""
+ path = QFileDialog.getExistingDirectory(
+ self, "选择 ETL 项目目录",
+ self.project_path_edit.text() or str(Path.home())
+ )
+ if path:
+ self.project_path_edit.setText(path)
+ # 自动填充 .env 路径
+ env_path = Path(path) / ".env"
+ if env_path.exists():
+ self.env_path_edit.setText(str(env_path))
+ self._validate_config()
+
+ def _browse_env_path(self):
+ """浏览 .env 文件"""
+ path, _ = QFileDialog.getOpenFileName(
+ self, "选择 .env 文件",
+ self.env_path_edit.text() or str(Path.home()),
+ "环境变量文件 (*.env);;所有文件 (*.*)"
+ )
+ if path:
+ self.env_path_edit.setText(path)
+ self._validate_config()
+
+ def _validate_config(self):
+ """验证配置"""
+ project_path = self.project_path_edit.text().strip()
+ env_path = self.env_path_edit.text().strip()
+
+ issues = []
+
+ if not project_path:
+ issues.append("• 未设置 ETL 项目路径")
+ else:
+ p = Path(project_path)
+ if not p.exists():
+ issues.append(f"• ETL 项目路径不存在")
+ elif not (p / "cli" / "main.py").exists():
+ issues.append(f"• 找不到 cli/main.py")
+
+ if not env_path:
+ issues.append("• 未设置 .env 文件路径")
+ elif not Path(env_path).exists():
+ issues.append("• .env 文件不存在")
+
+ if issues:
+ self.validation_label.setText("❌ 配置问题:\n" + "\n".join(issues))
+ self.validation_label.setStyleSheet("color: #d93025;")
+ else:
+ self.validation_label.setText("✅ 配置有效")
+ self.validation_label.setStyleSheet("color: #1e8e3e;")
+
+ def _save_and_accept(self):
+ """保存并关闭"""
+ project_path = self.project_path_edit.text().strip()
+ env_path = self.env_path_edit.text().strip()
+
+ # 简单验证
+ if project_path:
+ p = Path(project_path)
+ if not p.exists():
+ QMessageBox.warning(self, "警告", "ETL 项目路径不存在")
+ return
+ if not (p / "cli" / "main.py").exists():
+ reply = QMessageBox.question(
+ self, "确认",
+ "找不到 cli/main.py,确定要使用此路径吗?",
+ QMessageBox.Yes | QMessageBox.No
+ )
+ if reply == QMessageBox.No:
+ return
+
+ # 保存设置
+ app_settings.etl_project_path = project_path
+ if env_path:
+ app_settings.env_file_path = env_path
+
+ self.accept()
diff --git a/etl_billiards/gui/widgets/status_panel.py b/etl_billiards/gui/widgets/status_panel.py
new file mode 100644
index 0000000..9618860
--- /dev/null
+++ b/etl_billiards/gui/widgets/status_panel.py
@@ -0,0 +1,406 @@
+# -*- coding: utf-8 -*-
+"""ETL 状态面板"""
+
+from datetime import datetime
+from typing import Dict, List, Optional, Any
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
+ QGroupBox, QLabel, QPushButton, QTableWidget, QTableWidgetItem,
+ QHeaderView, QFrame, QScrollArea, QMessageBox
+)
+from PySide6.QtCore import Qt, Signal, QTimer
+from PySide6.QtGui import QColor
+
+from ..workers.db_worker import DBWorker
+from ..utils.config_helper import ConfigHelper
+
+
+class StatusCard(QFrame):
+ """状态卡片"""
+
+ def __init__(self, title: str, parent=None):
+ super().__init__(parent)
+ self.setProperty("card", True)
+ self.setFrameShape(QFrame.StyledPanel)
+
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 12, 16, 12)
+ layout.setSpacing(8)
+
+ # 标题
+ self.title_label = QLabel(title)
+ self.title_label.setProperty("subheading", True)
+ layout.addWidget(self.title_label)
+
+ # 值
+ self.value_label = QLabel("-")
+ self.value_label.setStyleSheet("font-size: 24px; font-weight: bold;")
+ layout.addWidget(self.value_label)
+
+ # 描述
+ self.desc_label = QLabel("")
+ self.desc_label.setProperty("subheading", True)
+ layout.addWidget(self.desc_label)
+
+ def set_value(self, value: str, description: str = "", status: str = ""):
+ """设置值"""
+ self.value_label.setText(value)
+ self.desc_label.setText(description)
+
+ if status:
+ self.value_label.setProperty("status", status)
+ self.value_label.style().unpolish(self.value_label)
+ self.value_label.style().polish(self.value_label)
+
+
+class StatusPanel(QWidget):
+ """ETL 状态面板"""
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.config_helper = ConfigHelper()
+ self.db_worker = DBWorker(self)
+ self._connected = False
+
+ self._init_ui()
+ self._connect_signals()
+
+ # 定时刷新
+ self.refresh_timer = QTimer(self)
+ self.refresh_timer.timeout.connect(self._auto_refresh)
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(16)
+
+ # 标题和按钮
+ header_layout = QHBoxLayout()
+
+ title = QLabel("ETL 状态")
+ title.setProperty("heading", True)
+ header_layout.addWidget(title)
+
+ header_layout.addStretch()
+
+ self.auto_refresh_btn = QPushButton("自动刷新: 关")
+ self.auto_refresh_btn.setProperty("secondary", True)
+ self.auto_refresh_btn.setCheckable(True)
+ header_layout.addWidget(self.auto_refresh_btn)
+
+ self.refresh_btn = QPushButton("刷新")
+ self.refresh_btn.clicked.connect(self._refresh_all)
+ header_layout.addWidget(self.refresh_btn)
+
+ layout.addLayout(header_layout)
+
+ # 连接状态
+ self.conn_status_label = QLabel("数据库: 未连接")
+ self.conn_status_label.setProperty("status", "warning")
+ layout.addWidget(self.conn_status_label)
+
+ # 滚动区域
+ scroll_area = QScrollArea()
+ scroll_area.setWidgetResizable(True)
+ scroll_area.setFrameShape(QFrame.NoFrame)
+ layout.addWidget(scroll_area, 1)
+
+ # 内容容器
+ content_widget = QWidget()
+ content_layout = QVBoxLayout(content_widget)
+ content_layout.setSpacing(16)
+
+ # 概览卡片
+ cards_layout = QHBoxLayout()
+
+ self.ods_card = StatusCard("ODS 表数量")
+ cards_layout.addWidget(self.ods_card)
+
+ self.dwd_card = StatusCard("DWD 表数量")
+ cards_layout.addWidget(self.dwd_card)
+
+ self.last_update_card = StatusCard("最后更新")
+ cards_layout.addWidget(self.last_update_card)
+
+ self.task_count_card = StatusCard("今日任务")
+ cards_layout.addWidget(self.task_count_card)
+
+ content_layout.addLayout(cards_layout)
+
+ # ODS Cutoff 状态
+ cutoff_group = QGroupBox("ODS Cutoff 状态")
+ cutoff_layout = QVBoxLayout(cutoff_group)
+
+ self.cutoff_table = QTableWidget()
+ self.cutoff_table.setColumnCount(4)
+ self.cutoff_table.setHorizontalHeaderLabels(["表名", "最新 fetched_at", "行数", "状态"])
+ self.cutoff_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
+ self.cutoff_table.setMaximumHeight(250)
+ cutoff_layout.addWidget(self.cutoff_table)
+
+ content_layout.addWidget(cutoff_group)
+
+ # 最近运行记录
+ history_group = QGroupBox("最近运行记录")
+ history_layout = QVBoxLayout(history_group)
+
+ self.history_table = QTableWidget()
+ self.history_table.setColumnCount(6)
+ self.history_table.setHorizontalHeaderLabels(["运行ID", "任务", "状态", "开始时间", "耗时", "影响行数"])
+ self.history_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
+ self.history_table.setMaximumHeight(250)
+ history_layout.addWidget(self.history_table)
+
+ content_layout.addWidget(history_group)
+
+ # 弹性空间
+ content_layout.addStretch()
+
+ scroll_area.setWidget(content_widget)
+
+ def _connect_signals(self):
+ """连接信号"""
+ self.auto_refresh_btn.toggled.connect(self._toggle_auto_refresh)
+ self.db_worker.connection_status.connect(self._on_connection_status)
+ self.db_worker.query_finished.connect(self._on_query_finished)
+ self.db_worker.query_error.connect(self._on_query_error)
+
+ def _toggle_auto_refresh(self, checked: bool):
+ """切换自动刷新"""
+ if checked:
+ self.auto_refresh_btn.setText("自动刷新: 开")
+ self.refresh_timer.start(30000) # 30秒刷新一次
+ self._refresh_all()
+ else:
+ self.auto_refresh_btn.setText("自动刷新: 关")
+ self.refresh_timer.stop()
+
+ def _auto_refresh(self):
+ """自动刷新"""
+ if self._connected:
+ self._refresh_all()
+
+ def _refresh_all(self):
+ """刷新所有数据"""
+ # 尝试连接数据库
+ if not self._connected:
+ env_vars = self.config_helper.load_env()
+ dsn = env_vars.get("PG_DSN", "")
+ if dsn:
+ self.db_worker.connect_db(dsn)
+ else:
+ self.conn_status_label.setText("数据库: 未配置 DSN")
+ return
+ else:
+ self._load_status_data()
+
+ def _on_connection_status(self, connected: bool, message: str):
+ """处理连接状态"""
+ self._connected = connected
+
+ if connected:
+ self.conn_status_label.setText(f"数据库: 已连接")
+ self.conn_status_label.setProperty("status", "success")
+ self._load_status_data()
+ else:
+ self.conn_status_label.setText(f"数据库: {message}")
+ self.conn_status_label.setProperty("status", "error")
+
+ self.conn_status_label.style().unpolish(self.conn_status_label)
+ self.conn_status_label.style().polish(self.conn_status_label)
+
+ def _load_status_data(self):
+ """加载状态数据"""
+ # 加载表统计
+ self._current_query = "table_count"
+ self.db_worker.execute_query("""
+ SELECT
+ table_schema,
+ COUNT(*) as table_count
+ FROM information_schema.tables
+ WHERE table_schema IN ('billiards_ods', 'billiards_dwd', 'billiards_dws')
+ GROUP BY table_schema
+ """)
+
+ def _on_query_finished(self, columns: list, rows: list):
+ """处理查询结果"""
+ query_type = getattr(self, '_current_query', '')
+
+ if query_type == "table_count":
+ self._process_table_count(rows)
+ # 继续加载 cutoff 数据
+ self._current_query = "cutoff"
+ self.db_worker.execute_query("""
+ SELECT
+ 'payment_transactions' AS table_name,
+ MAX(fetched_at) AS max_fetched_at,
+ COUNT(*) AS row_count
+ FROM billiards_ods.payment_transactions
+ UNION ALL
+ SELECT 'member_profiles', MAX(fetched_at), COUNT(*)
+ FROM billiards_ods.member_profiles
+ UNION ALL
+ SELECT 'settlement_records', MAX(fetched_at), COUNT(*)
+ FROM billiards_ods.settlement_records
+ UNION ALL
+ SELECT 'recharge_settlements', MAX(fetched_at), COUNT(*)
+ FROM billiards_ods.recharge_settlements
+ UNION ALL
+ SELECT 'assistant_service_records', MAX(fetched_at), COUNT(*)
+ FROM billiards_ods.assistant_service_records
+ ORDER BY table_name
+ """)
+ elif query_type == "cutoff":
+ self._process_cutoff_data(rows)
+ # 继续加载运行历史
+ self._current_query = "history"
+ self.db_worker.execute_query("""
+ SELECT
+ run_id,
+ task_code,
+ status,
+ started_at,
+ finished_at,
+ rows_affected
+ FROM etl_admin.run_tracker
+ ORDER BY started_at DESC
+ LIMIT 20
+ """)
+ elif query_type == "history":
+ self._process_history_data(rows)
+ self._current_query = ""
+
+ def _process_table_count(self, rows: list):
+ """处理表数量数据"""
+ ods_count = 0
+ dwd_count = 0
+
+ for row in rows:
+ schema = row.get("table_schema", "")
+ count = row.get("table_count", 0)
+
+ if schema == "billiards_ods":
+ ods_count = count
+ elif schema == "billiards_dwd":
+ dwd_count = count
+
+ self.ods_card.set_value(str(ods_count), "个表")
+ self.dwd_card.set_value(str(dwd_count), "个表")
+
+ def _process_cutoff_data(self, rows: list):
+ """处理 Cutoff 数据"""
+ self.cutoff_table.setRowCount(len(rows))
+
+ latest_time = None
+ now = datetime.now()
+
+ for row_idx, row in enumerate(rows):
+ table_name = row.get("table_name", "")
+ max_fetched = row.get("max_fetched_at")
+ row_count = row.get("row_count", 0)
+
+ self.cutoff_table.setItem(row_idx, 0, QTableWidgetItem(table_name))
+
+ if max_fetched:
+ time_str = str(max_fetched)[:19]
+ self.cutoff_table.setItem(row_idx, 1, QTableWidgetItem(time_str))
+
+ # 更新最新时间
+ if latest_time is None or max_fetched > latest_time:
+ latest_time = max_fetched
+
+ # 计算状态
+ if isinstance(max_fetched, datetime):
+ hours_ago = (now - max_fetched).total_seconds() / 3600
+ if hours_ago < 1:
+ status = "正常"
+ status_color = QColor("#1e8e3e")
+ elif hours_ago < 24:
+ status = "较新"
+ status_color = QColor("#1a73e8")
+ else:
+ status = f"落后 {int(hours_ago)}h"
+ status_color = QColor("#f9ab00")
+ else:
+ status = "-"
+ status_color = QColor("#9aa0a6")
+ else:
+ self.cutoff_table.setItem(row_idx, 1, QTableWidgetItem("-"))
+ status = "无数据"
+ status_color = QColor("#d93025")
+
+ self.cutoff_table.setItem(row_idx, 2, QTableWidgetItem(str(row_count)))
+
+ status_item = QTableWidgetItem(status)
+ status_item.setForeground(status_color)
+ self.cutoff_table.setItem(row_idx, 3, status_item)
+
+ # 更新最后更新时间卡片
+ if latest_time:
+ time_str = str(latest_time)[:16]
+ self.last_update_card.set_value(time_str, "")
+ else:
+ self.last_update_card.set_value("-", "无数据")
+
+ def _process_history_data(self, rows: list):
+ """处理运行历史数据"""
+ self.history_table.setRowCount(len(rows))
+
+ today_count = 0
+ today = datetime.now().date()
+
+ for row_idx, row in enumerate(rows):
+ run_id = row.get("run_id", "")
+ task_code = row.get("task_code", "")
+ status = row.get("status", "")
+ started_at = row.get("started_at")
+ finished_at = row.get("finished_at")
+ rows_affected = row.get("rows_affected", 0)
+
+ # 统计今日任务
+ if started_at and isinstance(started_at, datetime):
+ if started_at.date() == today:
+ today_count += 1
+
+ self.history_table.setItem(row_idx, 0, QTableWidgetItem(str(run_id)[:8] if run_id else "-"))
+ self.history_table.setItem(row_idx, 1, QTableWidgetItem(task_code))
+
+ # 状态
+ status_item = QTableWidgetItem(status)
+ if status and "success" in status.lower():
+ status_item.setForeground(QColor("#1e8e3e"))
+ elif status and ("fail" in status.lower() or "error" in status.lower()):
+ status_item.setForeground(QColor("#d93025"))
+ self.history_table.setItem(row_idx, 2, status_item)
+
+ # 开始时间
+ time_str = str(started_at)[:19] if started_at else "-"
+ self.history_table.setItem(row_idx, 3, QTableWidgetItem(time_str))
+
+ # 耗时
+ if started_at and finished_at:
+ try:
+ duration = (finished_at - started_at).total_seconds()
+ if duration < 60:
+ duration_str = f"{duration:.1f}秒"
+ else:
+ duration_str = f"{int(duration // 60)}分{int(duration % 60)}秒"
+ except:
+ duration_str = "-"
+ else:
+ duration_str = "-"
+ self.history_table.setItem(row_idx, 4, QTableWidgetItem(duration_str))
+
+ # 影响行数
+ self.history_table.setItem(row_idx, 5, QTableWidgetItem(str(rows_affected or 0)))
+
+ # 更新今日任务卡片
+ self.task_count_card.set_value(str(today_count), "次执行")
+
+ def _on_query_error(self, error: str):
+ """处理查询错误"""
+ self._current_query = ""
+ # 可能是表不存在,忽略错误继续
+ pass
diff --git a/etl_billiards/gui/widgets/task_manager.py b/etl_billiards/gui/widgets/task_manager.py
new file mode 100644
index 0000000..91f5689
--- /dev/null
+++ b/etl_billiards/gui/widgets/task_manager.py
@@ -0,0 +1,1948 @@
+# -*- coding: utf-8 -*-
+"""任务管理器面板"""
+
+import uuid
+from datetime import datetime, timedelta
+from typing import Dict, List, Optional
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QSplitter, QGridLayout,
+ QGroupBox, QLabel, QPushButton, QTableWidget, QTableWidgetItem,
+ QHeaderView, QMessageBox, QMenu, QAbstractItemView, QDialog,
+ QComboBox, QSpinBox, QLineEdit, QCheckBox, QTimeEdit, QDateEdit,
+ QListWidget, QListWidgetItem, QDialogButtonBox, QTabWidget, QFrame,
+ QTextEdit, QPlainTextEdit
+)
+from PySide6.QtCore import Qt, Signal, QTimer, QTime, QDate
+from PySide6.QtGui import QColor, QAction, QFont
+
+from ..models.task_model import QueuedTask, TaskConfig, TaskStatus
+from ..models.schedule_model import (
+ ScheduledTask, ScheduleConfig, ScheduleType, IntervalUnit, ScheduleStore,
+ ScheduleExecutionRecord
+)
+from ..utils.cli_builder import CLIBuilder
+from ..utils.app_settings import app_settings
+from ..workers.task_worker import TaskWorker
+
+
+# 可调度的任务列表(包含所有 ODS 任务 + DWD/质量检查任务)
+SCHEDULABLE_TASKS = [
+ # ODS 数据抓取任务(与 task_panel.AUTO_UPDATE_TASKS 保持一致)
+ ("ODS_PAYMENT", "支付流水"),
+ ("ODS_MEMBER", "会员档案"),
+ ("ODS_MEMBER_CARD", "会员储值卡"),
+ ("ODS_MEMBER_BALANCE", "会员余额变动"),
+ ("ODS_SETTLEMENT_RECORDS", "结账记录"),
+ ("ODS_TABLE_USE", "台费计费流水"),
+ ("ODS_ASSISTANT_ACCOUNT", "助教账号"),
+ ("ODS_ASSISTANT_LEDGER", "助教流水"),
+ ("ODS_ASSISTANT_ABOLISH", "助教作废"),
+ ("ODS_REFUND", "退款流水"),
+ ("ODS_PLATFORM_COUPON", "平台券核销"),
+ ("ODS_RECHARGE_SETTLE", "充值结算"),
+ ("ODS_SETTLEMENT_TICKET", "结账小票"),
+ # DWD 和质量检查任务
+ ("DWD_LOAD_FROM_ODS", "ODS→DWD 装载"),
+ ("DWD_QUALITY_CHECK", "DWD 质量检查"),
+ ("DATA_INTEGRITY_CHECK", "数据完整性检查"),
+ ("CHECK_CUTOFF", "检查 Cutoff"),
+]
+
+
+class TaskLogDialog(QDialog):
+ """任务日志查看对话框"""
+
+ def __init__(self, task: QueuedTask, parent=None):
+ super().__init__(parent)
+ self.task = task
+ self.setWindowTitle(f"任务日志 - {', '.join(task.config.tasks[:2])}")
+ self.setMinimumSize(800, 600)
+ self._init_ui()
+
+ def _init_ui(self):
+ layout = QVBoxLayout(self)
+
+ # 任务信息
+ info_group = QGroupBox("任务信息")
+ info_layout = QGridLayout(info_group)
+
+ info_layout.addWidget(QLabel("任务 ID:"), 0, 0)
+ info_layout.addWidget(QLabel(self.task.id), 0, 1)
+
+ info_layout.addWidget(QLabel("任务列表:"), 0, 2)
+ info_layout.addWidget(QLabel(", ".join(self.task.config.tasks)), 0, 3)
+
+ info_layout.addWidget(QLabel("状态:"), 1, 0)
+ status_label = QLabel(self._get_status_text(self.task.status))
+ status_label.setStyleSheet(f"color: {self._get_status_color(self.task.status)};")
+ info_layout.addWidget(status_label, 1, 1)
+
+ info_layout.addWidget(QLabel("退出码:"), 1, 2)
+ info_layout.addWidget(QLabel(str(self.task.exit_code) if self.task.exit_code is not None else "-"), 1, 3)
+
+ if self.task.started_at:
+ info_layout.addWidget(QLabel("开始时间:"), 2, 0)
+ info_layout.addWidget(QLabel(self.task.started_at.strftime("%Y-%m-%d %H:%M:%S")), 2, 1)
+
+ if self.task.finished_at:
+ info_layout.addWidget(QLabel("结束时间:"), 2, 2)
+ info_layout.addWidget(QLabel(self.task.finished_at.strftime("%Y-%m-%d %H:%M:%S")), 2, 3)
+
+ if self.task.started_at:
+ duration = (self.task.finished_at - self.task.started_at).total_seconds()
+ info_layout.addWidget(QLabel("耗时:"), 3, 0)
+ info_layout.addWidget(QLabel(f"{duration:.1f} 秒"), 3, 1)
+
+ layout.addWidget(info_group)
+
+ # 命令行
+ cmd_group = QGroupBox("执行命令")
+ cmd_layout = QVBoxLayout(cmd_group)
+ cmd_text = QLineEdit()
+ cmd_text.setReadOnly(True)
+ from ..utils.cli_builder import CLIBuilder
+ cli = CLIBuilder()
+ cmd_text.setText(cli.build_command_string(self.task.config))
+ cmd_layout.addWidget(cmd_text)
+
+ # 显示环境变量
+ if hasattr(self.task.config, 'env_vars') and self.task.config.env_vars:
+ env_label = QLabel("环境变量: " + ", ".join(f"{k}={v}" for k, v in self.task.config.env_vars.items()))
+ env_label.setWordWrap(True)
+ cmd_layout.addWidget(env_label)
+
+ layout.addWidget(cmd_group)
+
+ # 输出日志
+ log_group = QGroupBox("执行输出")
+ log_layout = QVBoxLayout(log_group)
+
+ self.log_text = QPlainTextEdit()
+ self.log_text.setReadOnly(True)
+ self.log_text.setFont(QFont("Consolas", 9))
+ self.log_text.setPlainText(self.task.output if self.task.output else "(无输出)")
+ log_layout.addWidget(self.log_text)
+
+ layout.addWidget(log_group)
+
+ # 错误信息
+ if self.task.error:
+ error_group = QGroupBox("错误信息")
+ error_layout = QVBoxLayout(error_group)
+ error_text = QPlainTextEdit()
+ error_text.setReadOnly(True)
+ error_text.setPlainText(self.task.error)
+ error_text.setMaximumHeight(100)
+ error_layout.addWidget(error_text)
+ layout.addWidget(error_group)
+
+ # 按钮
+ btn_layout = QHBoxLayout()
+
+ copy_btn = QPushButton("复制日志")
+ copy_btn.clicked.connect(self._copy_log)
+ btn_layout.addWidget(copy_btn)
+
+ btn_layout.addStretch()
+
+ close_btn = QPushButton("关闭")
+ close_btn.clicked.connect(self.accept)
+ btn_layout.addWidget(close_btn)
+
+ layout.addLayout(btn_layout)
+
+ def _copy_log(self):
+ """复制日志到剪贴板"""
+ from PySide6.QtWidgets import QApplication
+ QApplication.clipboard().setText(self.task.output or "")
+ QMessageBox.information(self, "提示", "日志已复制到剪贴板")
+
+ @staticmethod
+ def _get_status_text(status: TaskStatus) -> str:
+ return {
+ TaskStatus.PENDING: "待执行",
+ TaskStatus.RUNNING: "执行中",
+ TaskStatus.SUCCESS: "成功",
+ TaskStatus.FAILED: "失败",
+ TaskStatus.CANCELLED: "已取消",
+ }.get(status, "未知")
+
+ @staticmethod
+ def _get_status_color(status: TaskStatus) -> str:
+ return {
+ TaskStatus.PENDING: "#5f6368",
+ TaskStatus.RUNNING: "#1a73e8",
+ TaskStatus.SUCCESS: "#1e8e3e",
+ TaskStatus.FAILED: "#d93025",
+ TaskStatus.CANCELLED: "#9aa0a6",
+ }.get(status, "#333333")
+
+
+class ScheduleEditDialog(QDialog):
+ """调度任务编辑对话框"""
+
+ def __init__(self, task: Optional[ScheduledTask] = None, parent=None):
+ super().__init__(parent)
+ self.task = task
+ self.cli_builder = CLIBuilder()
+ self.setWindowTitle("编辑调度任务" if task else "新建调度任务")
+ self.setMinimumWidth(600)
+ self.setMinimumHeight(700)
+ self._init_ui()
+ self._connect_preview_signals()
+ if task:
+ self._load_task(task)
+ self._update_cli_preview() # 初始化预览
+
+ def _init_ui(self):
+ layout = QVBoxLayout(self)
+
+ # 基本信息
+ basic_group = QGroupBox("基本信息")
+ basic_layout = QGridLayout(basic_group)
+
+ basic_layout.addWidget(QLabel("任务名称:"), 0, 0)
+ self.name_edit = QLineEdit()
+ self.name_edit.setPlaceholderText("例: 每日数据更新")
+ basic_layout.addWidget(self.name_edit, 0, 1)
+
+ basic_layout.addWidget(QLabel("启用:"), 1, 0)
+ self.enabled_check = QCheckBox("启用此调度任务")
+ self.enabled_check.setChecked(True)
+ basic_layout.addWidget(self.enabled_check, 1, 1)
+
+ layout.addWidget(basic_group)
+
+ # 任务选择
+ task_group = QGroupBox("执行任务")
+ task_layout = QVBoxLayout(task_group)
+
+ self.task_list = QListWidget()
+ self.task_list.setSelectionMode(QListWidget.MultiSelection)
+ self.task_list.setMaximumHeight(150)
+ for code, name in SCHEDULABLE_TASKS:
+ item = QListWidgetItem(f"{name} ({code})")
+ item.setData(Qt.UserRole, code)
+ self.task_list.addItem(item)
+ task_layout.addWidget(self.task_list)
+
+ layout.addWidget(task_group)
+
+ # 调度设置
+ schedule_group = QGroupBox("调度设置")
+ schedule_layout = QVBoxLayout(schedule_group)
+
+ # 调度类型
+ type_layout = QHBoxLayout()
+ type_layout.addWidget(QLabel("调度类型:"))
+ self.schedule_type_combo = QComboBox()
+ self.schedule_type_combo.addItem("固定间隔", ScheduleType.INTERVAL)
+ self.schedule_type_combo.addItem("每天定时", ScheduleType.DAILY)
+ self.schedule_type_combo.addItem("每周定时", ScheduleType.WEEKLY)
+ self.schedule_type_combo.addItem("Cron 表达式", ScheduleType.CRON)
+ self.schedule_type_combo.currentIndexChanged.connect(self._on_type_changed)
+ type_layout.addWidget(self.schedule_type_combo, 1)
+ schedule_layout.addLayout(type_layout)
+
+ # 间隔设置
+ self.interval_widget = QWidget()
+ interval_layout = QHBoxLayout(self.interval_widget)
+ interval_layout.setContentsMargins(0, 0, 0, 0)
+ interval_layout.addWidget(QLabel("执行间隔:"))
+ self.interval_value = QSpinBox()
+ self.interval_value.setRange(1, 999)
+ self.interval_value.setValue(1)
+ interval_layout.addWidget(self.interval_value)
+ self.interval_unit = QComboBox()
+ self.interval_unit.addItem("分钟", IntervalUnit.MINUTES)
+ self.interval_unit.addItem("小时", IntervalUnit.HOURS)
+ self.interval_unit.addItem("天", IntervalUnit.DAYS)
+ self.interval_unit.setCurrentIndex(1) # 默认小时
+ interval_layout.addWidget(self.interval_unit)
+ interval_layout.addStretch()
+ schedule_layout.addWidget(self.interval_widget)
+
+ # 每日设置
+ self.daily_widget = QWidget()
+ daily_layout = QHBoxLayout(self.daily_widget)
+ daily_layout.setContentsMargins(0, 0, 0, 0)
+ daily_layout.addWidget(QLabel("执行时间:"))
+ self.daily_time = QTimeEdit()
+ self.daily_time.setTime(QTime(4, 0))
+ self.daily_time.setDisplayFormat("HH:mm")
+ daily_layout.addWidget(self.daily_time)
+ daily_layout.addStretch()
+ self.daily_widget.setVisible(False)
+ schedule_layout.addWidget(self.daily_widget)
+
+ # 每周设置
+ self.weekly_widget = QWidget()
+ weekly_layout = QVBoxLayout(self.weekly_widget)
+ weekly_layout.setContentsMargins(0, 0, 0, 0)
+
+ days_layout = QHBoxLayout()
+ days_layout.addWidget(QLabel("执行日:"))
+ self.day_checks = {}
+ for i, day in enumerate(["一", "二", "三", "四", "五", "六", "日"], 1):
+ check = QCheckBox(f"周{day}")
+ check.setChecked(i == 1) # 默认周一
+ self.day_checks[i] = check
+ days_layout.addWidget(check)
+ weekly_layout.addLayout(days_layout)
+
+ weekly_time_layout = QHBoxLayout()
+ weekly_time_layout.addWidget(QLabel("执行时间:"))
+ self.weekly_time = QTimeEdit()
+ self.weekly_time.setTime(QTime(4, 0))
+ self.weekly_time.setDisplayFormat("HH:mm")
+ weekly_time_layout.addWidget(self.weekly_time)
+ weekly_time_layout.addStretch()
+ weekly_layout.addLayout(weekly_time_layout)
+
+ self.weekly_widget.setVisible(False)
+ schedule_layout.addWidget(self.weekly_widget)
+
+ # Cron 设置
+ self.cron_widget = QWidget()
+ cron_layout = QHBoxLayout(self.cron_widget)
+ cron_layout.setContentsMargins(0, 0, 0, 0)
+ cron_layout.addWidget(QLabel("Cron:"))
+ self.cron_edit = QLineEdit()
+ self.cron_edit.setPlaceholderText("分 时 日 月 周 (例: 0 4 * * *)")
+ self.cron_edit.setText("0 4 * * *")
+ cron_layout.addWidget(self.cron_edit, 1)
+ self.cron_widget.setVisible(False)
+ schedule_layout.addWidget(self.cron_widget)
+
+ layout.addWidget(schedule_group)
+
+ # 任务配置
+ config_group = QGroupBox("任务配置")
+ config_layout = QGridLayout(config_group)
+
+ config_layout.addWidget(QLabel("运行模式:"), 0, 0)
+ self.pipeline_combo = QComboBox()
+ self.pipeline_combo.addItem("FULL - 在线抓取 + 入库", "FULL")
+ self.pipeline_combo.addItem("INGEST_ONLY - 仅入库", "INGEST_ONLY")
+ config_layout.addWidget(self.pipeline_combo, 0, 1)
+
+ config_layout.addWidget(QLabel("回溯小时:"), 1, 0)
+ self.lookback_hours = QSpinBox()
+ self.lookback_hours.setRange(1, 720)
+ self.lookback_hours.setValue(24)
+ self.lookback_hours.setSuffix(" 小时")
+ self.lookback_hours.setToolTip("每次执行时,抓取最近 N 小时的数据")
+ config_layout.addWidget(self.lookback_hours, 1, 1)
+
+ layout.addWidget(config_group)
+
+ # CLI 命令行预览
+ cli_group = QGroupBox("命令行预览")
+ cli_layout = QVBoxLayout(cli_group)
+
+ self.cli_preview = QPlainTextEdit()
+ self.cli_preview.setMaximumHeight(100)
+ self.cli_preview.setFont(QFont("Consolas", 9))
+ self.cli_preview.setPlaceholderText("CLI 命令行将在此显示...")
+ cli_layout.addWidget(self.cli_preview)
+
+ # CLI 编辑提示和复制按钮
+ cli_btn_layout = QHBoxLayout()
+ self.cli_editable_check = QCheckBox("允许手动编辑")
+ self.cli_editable_check.setToolTip("勾选后可以手动修改命令行参数")
+ self.cli_editable_check.stateChanged.connect(self._on_cli_editable_changed)
+ cli_btn_layout.addWidget(self.cli_editable_check)
+
+ cli_btn_layout.addStretch()
+
+ self.copy_cli_btn = QPushButton("复制命令")
+ self.copy_cli_btn.setProperty("secondary", True)
+ self.copy_cli_btn.clicked.connect(self._copy_cli_to_clipboard)
+ cli_btn_layout.addWidget(self.copy_cli_btn)
+
+ self.refresh_cli_btn = QPushButton("刷新预览")
+ self.refresh_cli_btn.setProperty("secondary", True)
+ self.refresh_cli_btn.clicked.connect(self._update_cli_preview)
+ cli_btn_layout.addWidget(self.refresh_cli_btn)
+
+ cli_layout.addLayout(cli_btn_layout)
+
+ layout.addWidget(cli_group)
+
+ # 按钮
+ btn_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+ btn_box.accepted.connect(self.accept)
+ btn_box.rejected.connect(self.reject)
+ layout.addWidget(btn_box)
+
+ def _on_type_changed(self, index: int):
+ schedule_type = self.schedule_type_combo.currentData()
+ self.interval_widget.setVisible(schedule_type == ScheduleType.INTERVAL)
+ self.daily_widget.setVisible(schedule_type == ScheduleType.DAILY)
+ self.weekly_widget.setVisible(schedule_type == ScheduleType.WEEKLY)
+ self.cron_widget.setVisible(schedule_type == ScheduleType.CRON)
+
+ def _load_task(self, task: ScheduledTask):
+ """加载任务数据"""
+ self.name_edit.setText(task.name)
+ self.enabled_check.setChecked(task.enabled)
+
+ # 选择任务
+ for i in range(self.task_list.count()):
+ item = self.task_list.item(i)
+ code = item.data(Qt.UserRole)
+ item.setSelected(code in task.task_codes)
+
+ # 调度设置
+ schedule = task.schedule
+
+ # 设置类型
+ for i in range(self.schedule_type_combo.count()):
+ if self.schedule_type_combo.itemData(i) == schedule.schedule_type:
+ self.schedule_type_combo.setCurrentIndex(i)
+ break
+
+ self.interval_value.setValue(schedule.interval_value)
+ for i in range(self.interval_unit.count()):
+ if self.interval_unit.itemData(i) == schedule.interval_unit:
+ self.interval_unit.setCurrentIndex(i)
+ break
+
+ if schedule.daily_time:
+ h, m = map(int, schedule.daily_time.split(":"))
+ self.daily_time.setTime(QTime(h, m))
+
+ for day, check in self.day_checks.items():
+ check.setChecked(day in schedule.weekly_days)
+
+ if schedule.weekly_time:
+ h, m = map(int, schedule.weekly_time.split(":"))
+ self.weekly_time.setTime(QTime(h, m))
+
+ self.cron_edit.setText(schedule.cron_expression)
+
+ # 任务配置
+ if task.task_config.get("pipeline_flow"):
+ for i in range(self.pipeline_combo.count()):
+ if self.pipeline_combo.itemData(i) == task.task_config["pipeline_flow"]:
+ self.pipeline_combo.setCurrentIndex(i)
+ break
+
+ self.lookback_hours.setValue(task.task_config.get("lookback_hours", 24))
+
+ def get_task(self) -> Optional[ScheduledTask]:
+ """获取配置的任务"""
+ name = self.name_edit.text().strip()
+ if not name:
+ QMessageBox.warning(self, "提示", "请输入任务名称")
+ return None
+
+ # 获取选中的任务
+ task_codes = []
+ for i in range(self.task_list.count()):
+ item = self.task_list.item(i)
+ if item.isSelected():
+ task_codes.append(item.data(Qt.UserRole))
+
+ if not task_codes:
+ QMessageBox.warning(self, "提示", "请至少选择一个任务")
+ return None
+
+ # 构建调度配置
+ schedule_type = self.schedule_type_combo.currentData()
+
+ weekly_days = [day for day, check in self.day_checks.items() if check.isChecked()]
+
+ schedule = ScheduleConfig(
+ schedule_type=schedule_type,
+ interval_value=self.interval_value.value(),
+ interval_unit=self.interval_unit.currentData(),
+ daily_time=self.daily_time.time().toString("HH:mm"),
+ weekly_days=weekly_days or [1],
+ weekly_time=self.weekly_time.time().toString("HH:mm"),
+ cron_expression=self.cron_edit.text().strip(),
+ enabled=True,
+ )
+
+ # 构建任务配置
+ task_config = {
+ "pipeline_flow": self.pipeline_combo.currentData(),
+ "lookback_hours": self.lookback_hours.value(),
+ }
+
+ # 创建或更新任务
+ if self.task:
+ task = self.task
+ task.name = name
+ task.task_codes = task_codes
+ task.schedule = schedule
+ task.task_config = task_config
+ task.enabled = self.enabled_check.isChecked()
+ else:
+ task = ScheduledTask(
+ id=str(uuid.uuid4())[:8],
+ name=name,
+ task_codes=task_codes,
+ schedule=schedule,
+ task_config=task_config,
+ enabled=self.enabled_check.isChecked(),
+ )
+
+ task.update_next_run()
+ return task
+
+ def _connect_preview_signals(self):
+ """连接信号以实时更新 CLI 预览"""
+ # 任务选择变化
+ self.task_list.itemSelectionChanged.connect(self._update_cli_preview)
+
+ # 调度配置变化
+ self.schedule_type_combo.currentIndexChanged.connect(self._update_cli_preview)
+ self.interval_value.valueChanged.connect(self._update_cli_preview)
+ self.interval_unit.currentIndexChanged.connect(self._update_cli_preview)
+
+ # 任务配置变化
+ self.pipeline_combo.currentIndexChanged.connect(self._update_cli_preview)
+ self.lookback_hours.valueChanged.connect(self._update_cli_preview)
+
+ def _update_cli_preview(self):
+ """更新 CLI 命令行预览"""
+ # 如果用户正在手动编辑,不自动更新
+ if self.cli_editable_check.isChecked():
+ return
+
+ # 获取选中的任务
+ task_codes = []
+ for i in range(self.task_list.count()):
+ item = self.task_list.item(i)
+ if item.isSelected():
+ task_codes.append(item.data(Qt.UserRole))
+
+ if not task_codes:
+ self.cli_preview.setPlainText("# 请选择至少一个任务")
+ return
+
+ # 获取配置
+ lookback_hours = self.lookback_hours.value()
+ pipeline_flow = self.pipeline_combo.currentData()
+
+ # 构建说明注释
+ lines = []
+
+ # 调度规则说明
+ schedule_type = self.schedule_type_combo.currentData()
+ if schedule_type == ScheduleType.INTERVAL:
+ interval_val = self.interval_value.value()
+ interval_unit = self.interval_unit.currentText()
+ lines.append(f"# 调度:每 {interval_val} {interval_unit} 执行一次")
+ elif schedule_type == ScheduleType.DAILY:
+ daily_time = self.daily_time.time().toString("HH:mm")
+ lines.append(f"# 调度:每天 {daily_time} 执行")
+ elif schedule_type == ScheduleType.WEEKLY:
+ weekly_time = self.weekly_time.time().toString("HH:mm")
+ days = [f"周{['一','二','三','四','五','六','日'][d-1]}"
+ for d, c in self.day_checks.items() if c.isChecked()]
+ lines.append(f"# 调度:每周 {','.join(days)} {weekly_time} 执行")
+ elif schedule_type == ScheduleType.CRON:
+ cron_expr = self.cron_edit.text().strip()
+ lines.append(f"# 调度:Cron 表达式 {cron_expr}")
+
+ # 动态时间窗口说明
+ lines.append(f"# 回溯窗口:{lookback_hours} 小时")
+ lines.append("#")
+ lines.append("# ⚠ 时间窗口在每次执行时动态计算:")
+ lines.append(f"# --window-start = <执行时间> - {lookback_hours}h")
+ lines.append(f"# --window-end = <执行时间>")
+ lines.append("")
+
+ # 生成命令行(使用占位符表示动态时间)
+ tasks_str = ",".join(task_codes)
+ cmd_parts = [
+ "python -m cli.main",
+ f"--tasks {tasks_str}",
+ f"--pipeline-flow {pipeline_flow}",
+ f'--window-start "<执行时间 - {lookback_hours}h>"',
+ f'--window-end "<执行时间>"',
+ ]
+ lines.append(" \\\n ".join(cmd_parts))
+
+ # 添加示例(使用当前时间作为示例)
+ lines.append("")
+ lines.append("# -------- 示例(假设现在执行)--------")
+ now = datetime.now()
+ start_time = now - timedelta(hours=lookback_hours)
+
+ # 构建示例 TaskConfig
+ config = TaskConfig(
+ tasks=task_codes,
+ pipeline_flow=pipeline_flow,
+ window_start=start_time.strftime("%Y-%m-%d %H:%M:%S"),
+ window_end=now.strftime("%Y-%m-%d %H:%M:%S"),
+ )
+ example_cmd = self.cli_builder.build_command_string(config)
+ lines.append(f"# {example_cmd}")
+
+ self.cli_preview.setPlainText("\n".join(lines))
+
+ def _on_cli_editable_changed(self, state):
+ """切换 CLI 编辑模式"""
+ editable = state == Qt.Checked
+ self.cli_preview.setReadOnly(not editable)
+
+ if editable:
+ # 切换到编辑模式,提示用户
+ current_text = self.cli_preview.toPlainText()
+ if not current_text.startswith("# [手动编辑模式]"):
+ self.cli_preview.setPlainText(f"# [手动编辑模式] 修改后点击「刷新预览」可恢复自动生成\n{current_text}")
+ else:
+ # 切换回只读模式,刷新预览
+ self._update_cli_preview()
+
+ def _copy_cli_to_clipboard(self):
+ """复制 CLI 命令到剪贴板"""
+ from PySide6.QtWidgets import QApplication
+ text = self.cli_preview.toPlainText()
+ # 提取实际命令行(跳过注释行)
+ lines = text.split('\n')
+ cmd_lines = [line for line in lines if line.strip() and not line.strip().startswith('#')]
+ cmd_text = '\n'.join(cmd_lines)
+
+ if cmd_text:
+ QApplication.clipboard().setText(cmd_text)
+ QMessageBox.information(self, "提示", "命令行已复制到剪贴板")
+ else:
+ QMessageBox.warning(self, "提示", "没有可复制的命令")
+
+
+class ScheduleLogDialog(QDialog):
+ """调度任务日志查看对话框"""
+
+ def __init__(self, scheduled_task: ScheduledTask, task_history: List[QueuedTask],
+ task_queue: List[QueuedTask] = None, parent=None):
+ super().__init__(parent)
+ self.scheduled_task = scheduled_task
+ self.task_history = task_history # 引用任务管理器的执行历史
+ self.task_queue = task_queue or [] # 引用任务队列(用于获取执行中任务的实时日志)
+ self.setWindowTitle(f"调度日志 - {scheduled_task.name}")
+ self.setMinimumSize(900, 600)
+ self._init_ui()
+
+ # 定时刷新执行中任务的日志
+ self._refresh_timer = QTimer(self)
+ self._refresh_timer.timeout.connect(self._refresh_running_log)
+ self._refresh_timer.start(1000) # 每秒刷新
+
+ def _init_ui(self):
+ layout = QVBoxLayout(self)
+
+ # 调度任务基本信息
+ info_group = QGroupBox("调度任务信息")
+ info_layout = QGridLayout(info_group)
+
+ info_layout.addWidget(QLabel("任务名称:"), 0, 0)
+ info_layout.addWidget(QLabel(self.scheduled_task.name), 0, 1)
+
+ info_layout.addWidget(QLabel("执行任务:"), 0, 2)
+ tasks_str = ", ".join(self.scheduled_task.task_codes[:3])
+ if len(self.scheduled_task.task_codes) > 3:
+ tasks_str += f" (+{len(self.scheduled_task.task_codes) - 3})"
+ info_layout.addWidget(QLabel(tasks_str), 0, 3)
+
+ info_layout.addWidget(QLabel("调度规则:"), 1, 0)
+ info_layout.addWidget(QLabel(self.scheduled_task.schedule.get_description()), 1, 1)
+
+ info_layout.addWidget(QLabel("执行次数:"), 1, 2)
+ info_layout.addWidget(QLabel(str(self.scheduled_task.run_count)), 1, 3)
+
+ layout.addWidget(info_group)
+
+ # 分割器
+ splitter = QSplitter(Qt.Vertical)
+ layout.addWidget(splitter, 1)
+
+ # 执行历史列表
+ history_group = QGroupBox(f"执行历史 (最近 {len(self.scheduled_task.execution_history)} 次)")
+ history_layout = QVBoxLayout(history_group)
+
+ self.history_table = QTableWidget()
+ self.history_table.setColumnCount(5)
+ self.history_table.setHorizontalHeaderLabels(["执行时间", "状态", "耗时", "退出码", "摘要"])
+ self.history_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
+ self.history_table.horizontalHeader().setSectionResizeMode(4, QHeaderView.Stretch)
+ self.history_table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.history_table.setSelectionMode(QAbstractItemView.SingleSelection)
+ self.history_table.itemSelectionChanged.connect(self._on_selection_changed)
+ history_layout.addWidget(self.history_table)
+
+ splitter.addWidget(history_group)
+
+ # 日志详情
+ log_group = QGroupBox("执行日志")
+ log_layout = QVBoxLayout(log_group)
+
+ self.log_text = QPlainTextEdit()
+ self.log_text.setReadOnly(True)
+ self.log_text.setFont(QFont("Consolas", 9))
+ self.log_text.setPlaceholderText("选择上方的执行记录查看详细日志...")
+ log_layout.addWidget(self.log_text)
+
+ splitter.addWidget(log_group)
+ splitter.setSizes([250, 350])
+
+ # 按钮
+ btn_layout = QHBoxLayout()
+
+ copy_btn = QPushButton("复制日志")
+ copy_btn.clicked.connect(self._copy_log)
+ btn_layout.addWidget(copy_btn)
+
+ btn_layout.addStretch()
+
+ close_btn = QPushButton("关闭")
+ close_btn.clicked.connect(self.accept)
+ btn_layout.addWidget(close_btn)
+
+ layout.addLayout(btn_layout)
+
+ # 填充历史表格
+ self._load_history()
+
+ def _load_history(self):
+ """加载执行历史"""
+ records = self.scheduled_task.execution_history
+ self.history_table.setRowCount(len(records))
+
+ for row, record in enumerate(records):
+ # 执行时间
+ time_str = record.executed_at.strftime("%Y-%m-%d %H:%M:%S")
+ self.history_table.setItem(row, 0, QTableWidgetItem(time_str))
+
+ # 状态
+ status_item = QTableWidgetItem(self._get_status_text(record.status))
+ status_item.setForeground(self._get_status_color(record.status))
+ self.history_table.setItem(row, 1, status_item)
+
+ # 耗时
+ if record.duration_seconds > 0:
+ if record.duration_seconds < 60:
+ duration_str = f"{record.duration_seconds:.1f}秒"
+ else:
+ mins = int(record.duration_seconds // 60)
+ secs = int(record.duration_seconds % 60)
+ duration_str = f"{mins}分{secs}秒"
+ else:
+ duration_str = "-"
+ self.history_table.setItem(row, 2, QTableWidgetItem(duration_str))
+
+ # 退出码
+ exit_str = str(record.exit_code) if record.exit_code is not None else "-"
+ self.history_table.setItem(row, 3, QTableWidgetItem(exit_str))
+
+ # 摘要
+ summary_item = QTableWidgetItem(record.summary[:50] if record.summary else "-")
+ summary_item.setData(Qt.UserRole, record.task_id) # 存储关联的任务ID
+ self.history_table.setItem(row, 4, summary_item)
+
+ # 自动选择第一行
+ if records:
+ self.history_table.selectRow(0)
+
+ def _on_selection_changed(self):
+ """选择变化时显示对应的日志"""
+ row = self.history_table.currentRow()
+ if row < 0 or row >= len(self.scheduled_task.execution_history):
+ self.log_text.clear()
+ return
+
+ record = self.scheduled_task.execution_history[row]
+
+ # 如果是执行中的任务,从任务队列获取实时日志
+ if record.status == "pending":
+ self._show_running_task_log(record)
+ return
+
+ # 优先使用执行记录中保存的日志
+ if record.output:
+ log_content = record.output
+ # 如果有错误信息,附加到末尾
+ if record.error:
+ log_content += f"\n\n===== 错误信息 =====\n{record.error}"
+ self.log_text.setPlainText(log_content)
+ else:
+ # 尝试从任务历史中查找(兼容旧记录)
+ queued_task = None
+ for task in self.task_history:
+ if task.id == record.task_id:
+ queued_task = task
+ break
+
+ if queued_task and queued_task.output:
+ self.log_text.setPlainText(queued_task.output)
+ else:
+ # 显示基本信息
+ info_lines = [
+ f"执行时间: {record.executed_at.strftime('%Y-%m-%d %H:%M:%S')}",
+ f"状态: {self._get_status_text(record.status)}",
+ f"耗时: {record.duration_seconds:.1f} 秒",
+ f"退出码: {record.exit_code}",
+ f"",
+ f"执行摘要:",
+ record.summary if record.summary else "(无)",
+ ]
+ if record.error:
+ info_lines.extend(["", "错误信息:", record.error])
+ self.log_text.setPlainText("\n".join(info_lines))
+
+ def _show_running_task_log(self, record: ScheduleExecutionRecord):
+ """显示执行中任务的实时日志"""
+ # 1. 先从任务队列中查找正在执行的任务
+ found_task = None
+ task_source = "queue"
+ for task in self.task_queue:
+ if task.id == record.task_id:
+ found_task = task
+ break
+
+ # 2. 如果队列中找不到,可能任务刚完成还在历史中,从历史中查找
+ if not found_task:
+ for task in self.task_history:
+ if task.id == record.task_id:
+ found_task = task
+ task_source = "history"
+ break
+
+ if found_task and found_task.output:
+ # 显示日志
+ if task_source == "queue" and found_task.status == TaskStatus.RUNNING:
+ # 任务还在执行中
+ header = f"===== 任务执行中 (实时日志) =====\n"
+ header += f"任务 ID: {found_task.id}\n"
+ if found_task.started_at:
+ elapsed = (datetime.now() - found_task.started_at).total_seconds()
+ header += f"已运行: {elapsed:.0f} 秒\n"
+ header += "=" * 40 + "\n\n"
+ else:
+ # 任务已完成(可能是刚完成,记录状态还没更新)
+ status_text = "成功" if found_task.status == TaskStatus.SUCCESS else "已完成"
+ if found_task.status == TaskStatus.FAILED:
+ status_text = "失败"
+ header = f"===== 任务 {status_text} =====\n"
+ header += f"任务 ID: {found_task.id}\n"
+ if found_task.started_at and found_task.finished_at:
+ duration = (found_task.finished_at - found_task.started_at).total_seconds()
+ header += f"执行耗时: {duration:.1f} 秒\n"
+ header += "=" * 40 + "\n\n"
+ self.log_text.setPlainText(header + found_task.output)
+ else:
+ # 任务可能还未开始
+ info_lines = [
+ "===== 任务执行中 =====",
+ f"任务 ID: {record.task_id}",
+ f"开始时间: {record.executed_at.strftime('%Y-%m-%d %H:%M:%S')}",
+ "",
+ "日志正在生成中,请稍候...",
+ "(日志将在任务执行过程中实时更新)",
+ ]
+ self.log_text.setPlainText("\n".join(info_lines))
+
+ def _refresh_running_log(self):
+ """定时刷新执行中任务的日志"""
+ row = self.history_table.currentRow()
+ if row < 0 or row >= len(self.scheduled_task.execution_history):
+ return
+
+ record = self.scheduled_task.execution_history[row]
+
+ # 检查任务是否还在执行中
+ if record.status == "pending":
+ # 保存当前滚动位置
+ scrollbar = self.log_text.verticalScrollBar()
+ at_bottom = scrollbar.value() >= scrollbar.maximum() - 10
+
+ # 检查任务是否已经完成(可能记录状态还没更新)
+ task_completed = False
+ for task in self.task_history:
+ if task.id == record.task_id:
+ task_completed = True
+ break
+
+ if task_completed:
+ # 任务已完成,刷新历史表格以更新状态显示
+ # 重新加载历史数据(从 schedule_store 获取最新状态)
+ # 注意:这里需要从父窗口重新获取调度任务的最新状态
+ self._show_running_task_log(record)
+ # 触发重新选择以更新显示
+ self._on_selection_changed()
+ else:
+ self._show_running_task_log(record)
+
+ # 如果之前在底部,保持在底部
+ if at_bottom:
+ scrollbar.setValue(scrollbar.maximum())
+
+ def _copy_log(self):
+ """复制日志到剪贴板"""
+ from PySide6.QtWidgets import QApplication
+ text = self.log_text.toPlainText()
+ if text:
+ QApplication.clipboard().setText(text)
+ QMessageBox.information(self, "提示", "日志已复制到剪贴板")
+
+ @staticmethod
+ def _get_status_text(status: str) -> str:
+ return {
+ "pending": "执行中",
+ "success": "成功",
+ "failed": "失败",
+ }.get(status, status or "未知")
+
+ @staticmethod
+ def _get_status_color(status: str) -> QColor:
+ return {
+ "pending": QColor("#1a73e8"),
+ "success": QColor("#1e8e3e"),
+ "failed": QColor("#d93025"),
+ }.get(status, QColor("#333333"))
+
+
+class TaskManager(QWidget):
+ """任务管理器"""
+
+ # 信号
+ task_started = Signal(str) # 任务开始
+ task_finished = Signal(bool, str) # 任务完成
+ log_message = Signal(str) # 日志消息
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.cli_builder = CLIBuilder()
+ self.task_queue: List[QueuedTask] = []
+ self.task_history: List[QueuedTask] = []
+ self.current_worker: Optional[TaskWorker] = None
+ self.auto_run = False
+
+ # 调度任务存储
+ self.schedule_store = ScheduleStore()
+ self.scheduler_enabled = False
+
+ # 任务ID到调度任务ID的映射,用于在任务完成时更新调度执行记录
+ self._task_schedule_mapping: Dict[str, str] = {}
+
+ self._init_ui()
+ self._connect_signals()
+
+ # 定时刷新
+ self.refresh_timer = QTimer(self)
+ self.refresh_timer.timeout.connect(self._refresh_display)
+ self.refresh_timer.start(1000) # 每秒刷新
+
+ # 调度检查定时器
+ self.schedule_timer = QTimer(self)
+ self.schedule_timer.timeout.connect(self._check_scheduled_tasks)
+
+ # 加载调度任务
+ self._refresh_schedule_table()
+
+ # 加载任务历史
+ self._load_task_history()
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(16)
+
+ # 标题
+ title = QLabel("任务管理")
+ title.setProperty("heading", True)
+ layout.addWidget(title)
+
+ # 使用选项卡
+ tab_widget = QTabWidget()
+ layout.addWidget(tab_widget, 1)
+
+ # ====== 任务队列选项卡 ======
+ queue_tab = QWidget()
+ queue_tab_layout = QVBoxLayout(queue_tab)
+ queue_tab_layout.setContentsMargins(0, 8, 0, 0)
+
+ # 控制按钮
+ header_layout = QHBoxLayout()
+ self.auto_run_btn = QPushButton("自动执行: 关")
+ self.auto_run_btn.setProperty("secondary", True)
+ self.auto_run_btn.setCheckable(True)
+ header_layout.addWidget(self.auto_run_btn)
+
+ self.clear_queue_btn = QPushButton("清空队列")
+ self.clear_queue_btn.setProperty("secondary", True)
+ header_layout.addWidget(self.clear_queue_btn)
+ header_layout.addStretch()
+ queue_tab_layout.addLayout(header_layout)
+
+ # 分割器
+ splitter = QSplitter(Qt.Vertical)
+ queue_tab_layout.addWidget(splitter, 1)
+
+ # 任务队列
+ queue_group = QGroupBox("任务队列")
+ queue_layout = QVBoxLayout(queue_group)
+
+ self.queue_table = QTableWidget()
+ self.queue_table.setColumnCount(5)
+ self.queue_table.setHorizontalHeaderLabels(["ID", "任务", "状态", "创建时间", "操作"])
+ self.queue_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
+ self.queue_table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.queue_table.setContextMenuPolicy(Qt.CustomContextMenu)
+ queue_layout.addWidget(self.queue_table)
+
+ queue_btn_layout = QHBoxLayout()
+ self.run_next_btn = QPushButton("执行下一个")
+ self.run_all_btn = QPushButton("执行全部")
+ self.stop_btn = QPushButton("停止当前")
+ self.stop_btn.setProperty("danger", True)
+ self.stop_btn.setEnabled(False)
+ queue_btn_layout.addWidget(self.run_next_btn)
+ queue_btn_layout.addWidget(self.run_all_btn)
+ queue_btn_layout.addStretch()
+ queue_btn_layout.addWidget(self.stop_btn)
+ queue_layout.addLayout(queue_btn_layout)
+
+ splitter.addWidget(queue_group)
+
+ # 实时日志
+ log_group = QGroupBox("执行日志 (实时)")
+ log_layout = QVBoxLayout(log_group)
+
+ self.live_log = QPlainTextEdit()
+ self.live_log.setReadOnly(True)
+ self.live_log.setFont(QFont("Consolas", 9))
+ self.live_log.setMaximumBlockCount(1000) # 限制行数
+ self.live_log.setPlaceholderText("任务执行时,日志将在此实时显示...")
+ log_layout.addWidget(self.live_log)
+
+ log_btn_layout = QHBoxLayout()
+ self.clear_log_btn = QPushButton("清空日志")
+ self.clear_log_btn.setProperty("secondary", True)
+ self.clear_log_btn.clicked.connect(self.live_log.clear)
+ self.auto_scroll_check = QCheckBox("自动滚动")
+ self.auto_scroll_check.setChecked(True)
+ log_btn_layout.addWidget(self.clear_log_btn)
+ log_btn_layout.addWidget(self.auto_scroll_check)
+ log_btn_layout.addStretch()
+ log_layout.addLayout(log_btn_layout)
+
+ splitter.addWidget(log_group)
+
+ # 执行历史
+ history_group = QGroupBox("执行历史")
+ history_layout = QVBoxLayout(history_group)
+
+ self.history_table = QTableWidget()
+ self.history_table.setColumnCount(6)
+ self.history_table.setHorizontalHeaderLabels(["ID", "任务", "状态", "开始时间", "耗时", "结果"])
+ self.history_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
+ self.history_table.horizontalHeader().setSectionResizeMode(5, QHeaderView.Stretch)
+ self.history_table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.history_table.setContextMenuPolicy(Qt.CustomContextMenu)
+ history_layout.addWidget(self.history_table)
+
+ # 提示标签
+ hint_label = QLabel("提示:双击任务可查看详细日志")
+ hint_label.setProperty("subheading", True)
+ history_layout.addWidget(hint_label)
+
+ history_btn_layout = QHBoxLayout()
+ self.clear_history_btn = QPushButton("清空历史")
+ self.clear_history_btn.setProperty("secondary", True)
+ history_btn_layout.addStretch()
+ history_btn_layout.addWidget(self.clear_history_btn)
+ history_layout.addLayout(history_btn_layout)
+
+ splitter.addWidget(history_group)
+ splitter.setSizes([200, 250, 250])
+
+ tab_widget.addTab(queue_tab, "任务队列")
+
+ # ====== 定时调度选项卡 ======
+ schedule_tab = QWidget()
+ schedule_layout = QVBoxLayout(schedule_tab)
+ schedule_layout.setContentsMargins(0, 8, 0, 0)
+
+ # 调度控制
+ schedule_header = QHBoxLayout()
+
+ self.scheduler_btn = QPushButton("调度器: 关")
+ self.scheduler_btn.setProperty("secondary", True)
+ self.scheduler_btn.setCheckable(True)
+ self.scheduler_btn.setToolTip("开启后将自动执行到期的调度任务")
+ schedule_header.addWidget(self.scheduler_btn)
+
+ schedule_header.addStretch()
+
+ self.add_schedule_btn = QPushButton("新建调度")
+ schedule_header.addWidget(self.add_schedule_btn)
+
+ schedule_layout.addLayout(schedule_header)
+
+ # 调度任务表格
+ self.schedule_table = QTableWidget()
+ self.schedule_table.setColumnCount(7)
+ self.schedule_table.setHorizontalHeaderLabels([
+ "名称", "任务", "调度", "下次执行", "上次执行", "执行次数", "状态"
+ ])
+ self.schedule_table.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents)
+ self.schedule_table.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch)
+ self.schedule_table.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeToContents)
+ self.schedule_table.setSelectionBehavior(QAbstractItemView.SelectRows)
+ self.schedule_table.setContextMenuPolicy(Qt.CustomContextMenu)
+ schedule_layout.addWidget(self.schedule_table, 1)
+
+ # 调度说明
+ schedule_note = QLabel(
+ "提示: 双击调度任务可查看执行日志。"
+ "调度器运行时会自动检查并执行到期的任务。"
+ "新建调度任务首次执行将延迟 60 秒。"
+ )
+ schedule_note.setProperty("subheading", True)
+ schedule_note.setWordWrap(True)
+ schedule_layout.addWidget(schedule_note)
+
+ tab_widget.addTab(schedule_tab, "定时调度")
+
+ def _connect_signals(self):
+ """连接信号"""
+ self.auto_run_btn.toggled.connect(self._toggle_auto_run)
+ self.clear_queue_btn.clicked.connect(self._clear_queue)
+ self.run_next_btn.clicked.connect(self._run_next)
+ self.run_all_btn.clicked.connect(self._run_all)
+ self.stop_btn.clicked.connect(self._stop_current)
+ self.clear_history_btn.clicked.connect(self._clear_history)
+ self.queue_table.customContextMenuRequested.connect(self._show_queue_menu)
+
+ # 历史表格
+ self.history_table.customContextMenuRequested.connect(self._show_history_menu)
+ self.history_table.doubleClicked.connect(self._view_task_log)
+
+ # 调度相关
+ self.scheduler_btn.toggled.connect(self._toggle_scheduler)
+ self.add_schedule_btn.clicked.connect(self._add_schedule)
+ self.schedule_table.customContextMenuRequested.connect(self._show_schedule_menu)
+ self.schedule_table.doubleClicked.connect(self._on_schedule_double_click)
+
+ def add_task(self, config: TaskConfig) -> str:
+ """添加任务到队列"""
+ task_id = str(uuid.uuid4())[:8]
+ task = QueuedTask(
+ id=task_id,
+ config=config,
+ status=TaskStatus.PENDING,
+ )
+ self.task_queue.append(task)
+ self._refresh_queue_table()
+
+ # 如果开启了自动执行且当前没有任务在运行
+ if self.auto_run and not self._is_running():
+ self._run_next()
+
+ return task_id
+
+ def _toggle_auto_run(self, checked: bool):
+ """切换自动执行"""
+ self.auto_run = checked
+ self.auto_run_btn.setText(f"自动执行: {'开' if checked else '关'}")
+
+ # 如果开启自动执行且有待执行任务
+ if checked and self.task_queue and not self._is_running():
+ self._run_next()
+
+ def _clear_queue(self):
+ """清空队列"""
+ # 只清除未执行的任务
+ self.task_queue = [t for t in self.task_queue if t.status == TaskStatus.RUNNING]
+ self._refresh_queue_table()
+
+ def _run_next(self):
+ """执行下一个任务"""
+ if self._is_running():
+ QMessageBox.information(self, "提示", "当前有任务正在执行")
+ return
+
+ # 找到下一个待执行的任务
+ for task in self.task_queue:
+ if task.status == TaskStatus.PENDING:
+ self._execute_task(task)
+ break
+
+ def _run_all(self):
+ """执行全部任务"""
+ self.auto_run = True
+ self.auto_run_btn.setChecked(True)
+ if not self._is_running():
+ self._run_next()
+
+ def _stop_current(self):
+ """停止当前任务"""
+ if self.current_worker and self.current_worker.isRunning():
+ self.current_worker.stop()
+
+ def _clear_history(self):
+ """清空历史"""
+ self.task_history.clear()
+ self._refresh_history_table()
+ self._save_task_history() # 保存到文件
+
+ def _execute_task(self, task: QueuedTask):
+ """执行任务"""
+ # 构建命令
+ cmd = self.cli_builder.build_command(task.config)
+
+ # 获取额外环境变量
+ extra_env = task.config.env_vars if hasattr(task.config, 'env_vars') else {}
+
+ # 创建工作线程
+ self.current_worker = TaskWorker(cmd, extra_env=extra_env)
+ self.current_worker.output_received.connect(lambda line: self._on_output(task, line))
+ self.current_worker.task_finished.connect(lambda code, summary: self._on_finished(task, code, summary))
+ self.current_worker.error_occurred.connect(lambda error: self._on_error(task, error))
+
+ # 更新任务状态
+ task.status = TaskStatus.RUNNING
+ task.started_at = datetime.now()
+
+ # 更新 UI
+ self.stop_btn.setEnabled(True)
+ self._refresh_queue_table()
+
+ # 发送信号
+ task_info = ",".join(task.config.tasks[:2])
+ if len(task.config.tasks) > 2:
+ task_info += f" 等{len(task.config.tasks)}个"
+ self.task_started.emit(task_info)
+
+ # 在实时日志中显示任务开始信息
+ self.live_log.appendPlainText("")
+ self.live_log.appendPlainText("=" * 60)
+ self.live_log.appendPlainText(f"▶ 开始执行任务: {task_info}")
+ self.live_log.appendPlainText(f" 任务 ID: {task.id}")
+ self.live_log.appendPlainText(f" 开始时间: {task.started_at.strftime('%Y-%m-%d %H:%M:%S')}")
+ self.live_log.appendPlainText("=" * 60)
+
+ # 启动
+ self.current_worker.start()
+
+ def _on_output(self, task: QueuedTask, line: str):
+ """收到输出"""
+ task.output += line + "\n"
+ self.log_message.emit(line)
+
+ # 显示到实时日志区域
+ timestamp = datetime.now().strftime("%H:%M:%S")
+ self.live_log.appendPlainText(f"[{timestamp}] {line}")
+
+ # 自动滚动
+ if self.auto_scroll_check.isChecked():
+ scrollbar = self.live_log.verticalScrollBar()
+ scrollbar.setValue(scrollbar.maximum())
+
+ def _on_finished(self, task: QueuedTask, exit_code: int, summary: str):
+ """任务完成"""
+ task.finished_at = datetime.now()
+ task.exit_code = exit_code
+
+ if exit_code == 0:
+ task.status = TaskStatus.SUCCESS
+ else:
+ task.status = TaskStatus.FAILED
+ task.error = summary
+
+ # 在实时日志中显示任务完成信息(详细报告)
+ duration = (task.finished_at - task.started_at).total_seconds() if task.started_at else 0
+ status_text = "✓ 成功" if exit_code == 0 else f"✗ 失败 (退出码: {exit_code})"
+
+ self.live_log.appendPlainText("")
+ self.live_log.appendPlainText("=" * 60)
+ self.live_log.appendPlainText(f"■ 任务执行报告")
+ self.live_log.appendPlainText("=" * 60)
+ self.live_log.appendPlainText(f" 状态: {status_text}")
+ self.live_log.appendPlainText(f" 任务 ID: {task.id}")
+ self.live_log.appendPlainText(f" 任务列表: {', '.join(task.config.tasks)}")
+ self.live_log.appendPlainText(f" 开始时间: {task.started_at.strftime('%Y-%m-%d %H:%M:%S') if task.started_at else '-'}")
+ self.live_log.appendPlainText(f" 结束时间: {task.finished_at.strftime('%Y-%m-%d %H:%M:%S') if task.finished_at else '-'}")
+
+ # 格式化耗时
+ if duration < 60:
+ duration_str = f"{duration:.1f} 秒"
+ elif duration < 3600:
+ mins = int(duration // 60)
+ secs = int(duration % 60)
+ duration_str = f"{mins} 分 {secs} 秒"
+ else:
+ hours = int(duration // 3600)
+ mins = int((duration % 3600) // 60)
+ duration_str = f"{hours} 时 {mins} 分"
+ self.live_log.appendPlainText(f" 总耗时: {duration_str}")
+
+ # 显示详细摘要
+ if summary:
+ self.live_log.appendPlainText("")
+ self.live_log.appendPlainText(" -------- 执行摘要 --------")
+ for line in summary.split('\n'):
+ self.live_log.appendPlainText(f" {line}")
+
+ self.live_log.appendPlainText("=" * 60)
+ self.live_log.appendPlainText("")
+
+ # 【重要】先更新调度执行记录(如果此任务来自调度),确保日志能正确保存
+ # 必须在移除任务之前执行,否则 ScheduleLogDialog 无法获取实时日志
+ self._update_schedule_execution_record(task, duration, summary)
+
+ # 移动到历史
+ self.task_queue.remove(task)
+ self.task_history.insert(0, task)
+
+ # 限制历史记录数量
+ if len(self.task_history) > 100:
+ self.task_history = self.task_history[:100]
+
+ # 保存历史到文件
+ self._save_task_history()
+
+ # 更新 UI
+ self.stop_btn.setEnabled(False)
+ self._refresh_queue_table()
+ self._refresh_history_table()
+ self._refresh_schedule_table()
+
+ # 发送信号
+ self.task_finished.emit(exit_code == 0, summary)
+
+ # 如果开启自动执行,或者队列中有定时任务待执行,继续下一个
+ if self.auto_run or self._has_scheduled_tasks_pending():
+ QTimer.singleShot(500, self._run_next)
+
+ def _on_error(self, task: QueuedTask, error: str):
+ """发生错误"""
+ task.error = error
+ self.log_message.emit(f"[错误] {error}")
+
+ def _is_running(self) -> bool:
+ """是否有任务在运行"""
+ return self.current_worker is not None and self.current_worker.isRunning()
+
+ def _has_scheduled_tasks_pending(self) -> bool:
+ """检查队列中是否有待执行的定时任务"""
+ for task in self.task_queue:
+ if task.status == TaskStatus.PENDING and task.id in self._task_schedule_mapping:
+ return True
+ return False
+
+ def _refresh_display(self):
+ """刷新显示"""
+ # 更新运行中任务的状态
+ if self._is_running():
+ for row in range(self.queue_table.rowCount()):
+ status_item = self.queue_table.item(row, 2)
+ if status_item and status_item.text() == "执行中":
+ # 添加动画效果
+ dots = "." * (int(datetime.now().timestamp()) % 4)
+ status_item.setText(f"执行中{dots}")
+
+ def _refresh_queue_table(self):
+ """刷新队列表格"""
+ self.queue_table.setRowCount(len(self.task_queue))
+
+ for row, task in enumerate(self.task_queue):
+ # ID
+ self.queue_table.setItem(row, 0, QTableWidgetItem(task.id))
+
+ # 任务
+ tasks_str = ", ".join(task.config.tasks[:3])
+ if len(task.config.tasks) > 3:
+ tasks_str += f" (+{len(task.config.tasks) - 3})"
+ self.queue_table.setItem(row, 1, QTableWidgetItem(tasks_str))
+
+ # 状态
+ status_item = QTableWidgetItem(self._get_status_text(task.status))
+ status_item.setForeground(self._get_status_color(task.status))
+ self.queue_table.setItem(row, 2, status_item)
+
+ # 创建时间
+ time_str = task.created_at.strftime("%H:%M:%S")
+ self.queue_table.setItem(row, 3, QTableWidgetItem(time_str))
+
+ # 操作按钮
+ self.queue_table.setItem(row, 4, QTableWidgetItem(""))
+
+ def _refresh_history_table(self):
+ """刷新历史表格"""
+ self.history_table.setRowCount(len(self.task_history))
+
+ for row, task in enumerate(self.task_history):
+ # ID
+ self.history_table.setItem(row, 0, QTableWidgetItem(task.id))
+
+ # 任务
+ tasks_str = ", ".join(task.config.tasks[:3])
+ if len(task.config.tasks) > 3:
+ tasks_str += f" (+{len(task.config.tasks) - 3})"
+ self.history_table.setItem(row, 1, QTableWidgetItem(tasks_str))
+
+ # 状态
+ status_item = QTableWidgetItem(self._get_status_text(task.status))
+ status_item.setForeground(self._get_status_color(task.status))
+ self.history_table.setItem(row, 2, status_item)
+
+ # 开始时间
+ time_str = task.started_at.strftime("%Y-%m-%d %H:%M:%S") if task.started_at else "-"
+ self.history_table.setItem(row, 3, QTableWidgetItem(time_str))
+
+ # 耗时
+ if task.started_at and task.finished_at:
+ duration = (task.finished_at - task.started_at).total_seconds()
+ if duration < 60:
+ duration_str = f"{duration:.1f}秒"
+ else:
+ duration_str = f"{int(duration // 60)}分{int(duration % 60)}秒"
+ else:
+ duration_str = "-"
+ self.history_table.setItem(row, 4, QTableWidgetItem(duration_str))
+
+ # 结果 - 提取摘要的第一行作为显示
+ if task.status == TaskStatus.SUCCESS:
+ # 从 output 中提取摘要信息
+ result = self._extract_result_summary(task)
+ else:
+ result = task.error if task.error else "失败"
+
+ # 显示结果(取第一行,最多80字符)
+ result_display = result.split('\n')[0][:80] if result else "成功"
+ result_item = QTableWidgetItem(result_display)
+ result_item.setToolTip(result) # 完整内容作为 tooltip
+ self.history_table.setItem(row, 5, result_item)
+
+ def _show_queue_menu(self, pos):
+ """显示队列右键菜单"""
+ item = self.queue_table.itemAt(pos)
+ if not item:
+ return
+
+ row = item.row()
+ if row >= len(self.task_queue):
+ return
+
+ task = self.task_queue[row]
+
+ menu = QMenu(self)
+
+ if task.status == TaskStatus.PENDING:
+ run_action = QAction("立即执行", self)
+ run_action.triggered.connect(lambda: self._execute_task(task))
+ menu.addAction(run_action)
+
+ remove_action = QAction("移除", self)
+ remove_action.triggered.connect(lambda: self._remove_task(task))
+ menu.addAction(remove_action)
+ elif task.status == TaskStatus.RUNNING:
+ stop_action = QAction("停止", self)
+ stop_action.triggered.connect(self._stop_current)
+ menu.addAction(stop_action)
+
+ menu.exec(self.queue_table.mapToGlobal(pos))
+
+ def _remove_task(self, task: QueuedTask):
+ """移除任务"""
+ if task in self.task_queue:
+ self.task_queue.remove(task)
+ self._refresh_queue_table()
+
+ def _show_history_menu(self, pos):
+ """显示历史右键菜单"""
+ item = self.history_table.itemAt(pos)
+ if not item:
+ return
+
+ row = item.row()
+ if row >= len(self.task_history):
+ return
+
+ task = self.task_history[row]
+
+ menu = QMenu(self)
+
+ view_action = QAction("查看日志", self)
+ view_action.triggered.connect(lambda: self._show_task_log_dialog(task))
+ menu.addAction(view_action)
+
+ rerun_action = QAction("重新执行", self)
+ rerun_action.triggered.connect(lambda: self._rerun_task(task))
+ menu.addAction(rerun_action)
+
+ menu.addSeparator()
+
+ remove_action = QAction("从历史删除", self)
+ remove_action.triggered.connect(lambda: self._remove_from_history(task))
+ menu.addAction(remove_action)
+
+ menu.exec(self.history_table.mapToGlobal(pos))
+
+ def _view_task_log(self, index):
+ """双击查看任务日志"""
+ row = index.row()
+ if row < len(self.task_history):
+ self._show_task_log_dialog(self.task_history[row])
+
+ def _show_task_log_dialog(self, task: QueuedTask):
+ """显示任务日志对话框"""
+ dialog = TaskLogDialog(task, self)
+ dialog.exec()
+
+ def _rerun_task(self, task: QueuedTask):
+ """重新执行任务"""
+ # 创建新任务(使用相同配置)
+ self.add_task(task.config)
+ QMessageBox.information(self, "提示", "任务已添加到队列")
+
+ def _remove_from_history(self, task: QueuedTask):
+ """从历史中删除任务"""
+ if task in self.task_history:
+ self.task_history.remove(task)
+ self._refresh_history_table()
+ self._save_task_history() # 保存到文件
+
+ def _load_task_history(self):
+ """从文件加载任务历史"""
+ try:
+ history_data = app_settings.load_task_history()
+ for item in history_data:
+ try:
+ # 重建 TaskConfig
+ config = TaskConfig(
+ tasks=item.get("tasks", []),
+ pipeline_flow=item.get("pipeline_flow", "FULL"),
+ window_start=item.get("window_start"),
+ window_end=item.get("window_end"),
+ )
+
+ # 重建 QueuedTask
+ status_str = item.get("status", "success")
+ status_map = {
+ "pending": TaskStatus.PENDING,
+ "running": TaskStatus.RUNNING,
+ "success": TaskStatus.SUCCESS,
+ "failed": TaskStatus.FAILED,
+ "cancelled": TaskStatus.CANCELLED,
+ }
+ status = status_map.get(status_str, TaskStatus.SUCCESS)
+
+ task = QueuedTask(
+ id=item.get("id", "unknown"),
+ config=config,
+ status=status,
+ )
+
+ # 恢复时间
+ if item.get("created_at"):
+ task.created_at = datetime.fromisoformat(item["created_at"])
+ if item.get("started_at"):
+ task.started_at = datetime.fromisoformat(item["started_at"])
+ if item.get("finished_at"):
+ task.finished_at = datetime.fromisoformat(item["finished_at"])
+
+ task.exit_code = item.get("exit_code")
+ task.error = item.get("error", "")
+ task.output = item.get("output_preview", "")
+
+ self.task_history.append(task)
+ except Exception:
+ continue
+
+ # 刷新显示
+ self._refresh_history_table()
+
+ if self.task_history:
+ self.log_message.emit(f"[系统] 已加载 {len(self.task_history)} 条历史任务记录")
+ except Exception as e:
+ print(f"加载任务历史失败: {e}")
+
+ def _save_task_history(self):
+ """保存任务历史到文件"""
+ try:
+ app_settings.save_task_history(self.task_history)
+ except Exception as e:
+ print(f"保存任务历史失败: {e}")
+
+ def _extract_result_summary(self, task: QueuedTask) -> str:
+ """从任务输出中提取结果摘要"""
+ import re
+
+ if not task.output:
+ return "成功"
+
+ lines = task.output.split('\n')
+ summary_parts = []
+
+ # 统计关键数据
+ total_inserted = 0
+ total_missing = 0
+ total_records = 0
+
+ for line in lines:
+ # 解析 DWD 装载统计
+ if "完成,统计=" in line:
+ try:
+ match = re.search(r"统计=(\{.+\})", line)
+ if match:
+ import json
+ stats_str = match.group(1).replace("'", '"')
+ stats = json.loads(stats_str)
+ if 'tables' in stats:
+ for tbl in stats['tables']:
+ inserted = tbl.get('inserted', 0)
+ processed = tbl.get('processed', 0)
+ total_inserted += inserted + processed
+ except Exception:
+ pass
+
+ # 解析数据校验结果
+ if "结果统计:" in line or "结果统计:" in line:
+ try:
+ match = re.search(r"\{.+\}", line)
+ if match:
+ import json
+ stats_str = match.group(0).replace("'", '"')
+ stats = json.loads(stats_str)
+ total_missing = stats.get('missing', 0)
+ except Exception:
+ pass
+
+ # 解析 CHECK_DONE
+ match = re.search(r'CHECK_DONE.*records=(\d+)', line)
+ if match:
+ total_records += int(match.group(1))
+
+ # 构建摘要
+ if total_inserted > 0:
+ summary_parts.append(f"处理 {total_inserted} 条")
+
+ if total_records > 0:
+ if total_missing > 0:
+ summary_parts.append(f"校验 {total_records} 条, 缺失 {total_missing}")
+ else:
+ summary_parts.append(f"校验 {total_records} 条, 数据完整")
+
+ if summary_parts:
+ return " | ".join(summary_parts)
+
+ return "成功"
+
+ @staticmethod
+ def _get_status_text(status: TaskStatus) -> str:
+ """获取状态文本"""
+ return {
+ TaskStatus.PENDING: "待执行",
+ TaskStatus.RUNNING: "执行中",
+ TaskStatus.SUCCESS: "成功",
+ TaskStatus.FAILED: "失败",
+ TaskStatus.CANCELLED: "已取消",
+ }.get(status, "未知")
+
+ @staticmethod
+ def _get_status_color(status: TaskStatus) -> QColor:
+ """获取状态颜色"""
+ return {
+ TaskStatus.PENDING: QColor("#5f6368"),
+ TaskStatus.RUNNING: QColor("#1a73e8"),
+ TaskStatus.SUCCESS: QColor("#1e8e3e"),
+ TaskStatus.FAILED: QColor("#d93025"),
+ TaskStatus.CANCELLED: QColor("#9aa0a6"),
+ }.get(status, QColor("#333333"))
+
+ # ========== 调度相关方法 ==========
+
+ def _toggle_scheduler(self, checked: bool):
+ """切换调度器状态"""
+ self.scheduler_enabled = checked
+ self.scheduler_btn.setText(f"调度器: {'开' if checked else '关'}")
+
+ if checked:
+ # 启动调度检查定时器(每分钟检查一次)
+ self.schedule_timer.start(60000)
+ # 立即检查一次
+ self._check_scheduled_tasks()
+ self.log_message.emit("[调度器] 已启动")
+ else:
+ self.schedule_timer.stop()
+ self.log_message.emit("[调度器] 已停止")
+
+ def _check_scheduled_tasks(self):
+ """检查并执行到期的调度任务"""
+ if not self.scheduler_enabled:
+ return
+
+ due_tasks = self.schedule_store.get_due_tasks()
+ for task in due_tasks:
+ self._execute_scheduled_task(task)
+
+ def _execute_scheduled_task(self, scheduled_task: ScheduledTask):
+ """执行调度任务"""
+ # 构建任务配置
+ lookback_hours = scheduled_task.task_config.get("lookback_hours", 24)
+ now = datetime.now()
+ start_time = now - timedelta(hours=lookback_hours)
+
+ config = TaskConfig(
+ tasks=scheduled_task.task_codes,
+ pipeline_flow=scheduled_task.task_config.get("pipeline_flow", "FULL"),
+ window_start=start_time.strftime("%Y-%m-%d %H:%M:%S"),
+ window_end=now.strftime("%Y-%m-%d %H:%M:%S"),
+ )
+
+ # 添加到队列
+ task_id = self.add_task(config)
+
+ # 创建执行记录
+ execution_record = ScheduleExecutionRecord(
+ task_id=task_id,
+ executed_at=now,
+ status="pending",
+ )
+ scheduled_task.add_execution_record(execution_record)
+
+ # 保存映射关系,以便任务完成时更新记录
+ self._task_schedule_mapping[task_id] = scheduled_task.id
+
+ # 更新调度任务状态
+ scheduled_task.last_run = now
+ scheduled_task.run_count += 1
+ scheduled_task.last_status = "执行中"
+ scheduled_task.update_next_run()
+ self.schedule_store.update_task(scheduled_task)
+
+ self._refresh_schedule_table()
+ self.log_message.emit(f"[调度器] 执行任务: {scheduled_task.name} (ID: {task_id})")
+
+ # 定时任务必须立即启动执行,不受 auto_run 设置影响
+ if not self._is_running():
+ # 从队列中找到刚添加的任务并执行
+ for queued_task in self.task_queue:
+ if queued_task.id == task_id:
+ self._execute_task(queued_task)
+ break
+
+ def _add_schedule(self):
+ """添加调度任务"""
+ dialog = ScheduleEditDialog(parent=self)
+ if dialog.exec() == QDialog.Accepted:
+ task = dialog.get_task()
+ if task:
+ self.schedule_store.add_task(task)
+ self._refresh_schedule_table()
+ self.log_message.emit(f"[调度器] 已创建任务: {task.name}")
+
+ def _edit_schedule(self):
+ """编辑调度任务"""
+ row = self.schedule_table.currentRow()
+ if row < 0:
+ return
+
+ tasks = self.schedule_store.get_all_tasks()
+ if row >= len(tasks):
+ return
+
+ task = tasks[row]
+ dialog = ScheduleEditDialog(task=task, parent=self)
+ if dialog.exec() == QDialog.Accepted:
+ updated_task = dialog.get_task()
+ if updated_task:
+ self.schedule_store.update_task(updated_task)
+ self._refresh_schedule_table()
+ self.log_message.emit(f"[调度器] 已更新任务: {updated_task.name}")
+
+ def _delete_schedule(self, task_id: str):
+ """删除调度任务"""
+ task = self.schedule_store.get_task(task_id)
+ if not task:
+ return
+
+ reply = QMessageBox.question(
+ self,
+ "确认删除",
+ f"确定要删除调度任务 '{task.name}' 吗?",
+ QMessageBox.Yes | QMessageBox.No,
+ QMessageBox.No
+ )
+
+ if reply == QMessageBox.Yes:
+ self.schedule_store.remove_task(task_id)
+ self._refresh_schedule_table()
+ self.log_message.emit(f"[调度器] 已删除任务: {task.name}")
+
+ def _toggle_schedule_enabled(self, task_id: str):
+ """切换调度任务启用状态"""
+ task = self.schedule_store.get_task(task_id)
+ if task:
+ task.enabled = not task.enabled
+ task.update_next_run()
+ self.schedule_store.update_task(task)
+ self._refresh_schedule_table()
+ status = "启用" if task.enabled else "禁用"
+ self.log_message.emit(f"[调度器] {task.name}: {status}")
+
+ def _run_schedule_now(self, task_id: str):
+ """立即执行调度任务"""
+ task = self.schedule_store.get_task(task_id)
+ if task:
+ self._execute_scheduled_task(task)
+
+ def _show_schedule_menu(self, pos):
+ """显示调度任务右键菜单"""
+ item = self.schedule_table.itemAt(pos)
+ if not item:
+ return
+
+ row = item.row()
+ tasks = self.schedule_store.get_all_tasks()
+ if row >= len(tasks):
+ return
+
+ task = tasks[row]
+
+ menu = QMenu(self)
+
+ # 查看日志
+ log_action = QAction("查看执行日志", self)
+ log_action.triggered.connect(lambda: self._view_schedule_log(task.id))
+ menu.addAction(log_action)
+
+ menu.addSeparator()
+
+ # 立即执行
+ run_action = QAction("立即执行", self)
+ run_action.triggered.connect(lambda: self._run_schedule_now(task.id))
+ menu.addAction(run_action)
+
+ # 编辑
+ edit_action = QAction("编辑", self)
+ edit_action.triggered.connect(self._edit_schedule)
+ menu.addAction(edit_action)
+
+ menu.addSeparator()
+
+ # 启用/禁用
+ toggle_text = "禁用" if task.enabled else "启用"
+ toggle_action = QAction(toggle_text, self)
+ toggle_action.triggered.connect(lambda: self._toggle_schedule_enabled(task.id))
+ menu.addAction(toggle_action)
+
+ menu.addSeparator()
+
+ # 删除
+ delete_action = QAction("删除", self)
+ delete_action.triggered.connect(lambda: self._delete_schedule(task.id))
+ menu.addAction(delete_action)
+
+ menu.exec(self.schedule_table.mapToGlobal(pos))
+
+ def _refresh_schedule_table(self):
+ """刷新调度任务表格"""
+ tasks = self.schedule_store.get_all_tasks()
+ self.schedule_table.setRowCount(len(tasks))
+
+ for row, task in enumerate(tasks):
+ # 名称
+ name_item = QTableWidgetItem(task.name)
+ name_item.setData(Qt.UserRole, task.id)
+ self.schedule_table.setItem(row, 0, name_item)
+
+ # 任务
+ tasks_str = ", ".join(task.task_codes[:2])
+ if len(task.task_codes) > 2:
+ tasks_str += f" (+{len(task.task_codes) - 2})"
+ self.schedule_table.setItem(row, 1, QTableWidgetItem(tasks_str))
+
+ # 调度
+ self.schedule_table.setItem(row, 2, QTableWidgetItem(task.schedule.get_description()))
+
+ # 下次执行
+ if task.next_run:
+ next_str = task.next_run.strftime("%m-%d %H:%M")
+ else:
+ next_str = "-"
+ self.schedule_table.setItem(row, 3, QTableWidgetItem(next_str))
+
+ # 上次执行
+ if task.last_run:
+ last_str = task.last_run.strftime("%m-%d %H:%M")
+ else:
+ last_str = "-"
+ self.schedule_table.setItem(row, 4, QTableWidgetItem(last_str))
+
+ # 执行次数
+ self.schedule_table.setItem(row, 5, QTableWidgetItem(str(task.run_count)))
+
+ # 状态
+ if task.enabled:
+ status_text = "启用"
+ status_color = QColor("#1e8e3e")
+ else:
+ status_text = "禁用"
+ status_color = QColor("#9aa0a6")
+ status_item = QTableWidgetItem(status_text)
+ status_item.setForeground(status_color)
+ self.schedule_table.setItem(row, 6, status_item)
+
+ def _update_schedule_execution_record(self, task: QueuedTask, duration: float, summary: str):
+ """更新调度执行记录(如果此任务来自调度)"""
+ schedule_id = self._task_schedule_mapping.get(task.id)
+ if not schedule_id:
+ return
+
+ # 从映射中移除(一次性)
+ del self._task_schedule_mapping[task.id]
+
+ # 获取调度任务
+ scheduled_task = self.schedule_store.get_task(schedule_id)
+ if not scheduled_task:
+ return
+
+ # 更新执行记录(包含完整日志)
+ status = "success" if task.status == TaskStatus.SUCCESS else "failed"
+ scheduled_task.update_execution_record(
+ task_id=task.id,
+ status=status,
+ exit_code=task.exit_code or 0,
+ duration=duration,
+ summary=summary or self._extract_result_summary(task),
+ output=task.output or "",
+ error=task.error or "",
+ )
+
+ # 更新调度任务状态
+ scheduled_task.last_status = "成功" if status == "success" else "失败"
+
+ # 保存
+ self.schedule_store.update_task(scheduled_task)
+ self.log_message.emit(f"[调度器] 任务 {scheduled_task.name} 执行完成: {scheduled_task.last_status}")
+
+ def _view_schedule_log(self, task_id: str):
+ """查看调度任务日志"""
+ task = self.schedule_store.get_task(task_id)
+ if not task:
+ QMessageBox.warning(self, "提示", "未找到调度任务")
+ return
+
+ if not task.execution_history:
+ QMessageBox.information(self, "提示", "该调度任务尚无执行记录")
+ return
+
+ # 传递 task_queue 以便获取执行中任务的实时日志
+ dialog = ScheduleLogDialog(task, self.task_history, self.task_queue, self)
+ dialog.exec()
+
+ def _on_schedule_double_click(self, index):
+ """双击调度任务查看日志"""
+ row = index.row()
+ tasks = self.schedule_store.get_all_tasks()
+ if row < len(tasks):
+ self._view_schedule_log(tasks[row].id)
diff --git a/etl_billiards/gui/widgets/task_panel.py b/etl_billiards/gui/widgets/task_panel.py
new file mode 100644
index 0000000..1880b57
--- /dev/null
+++ b/etl_billiards/gui/widgets/task_panel.py
@@ -0,0 +1,1061 @@
+# -*- coding: utf-8 -*-
+"""任务配置面板"""
+
+from datetime import datetime, timedelta
+
+from PySide6.QtWidgets import (
+ QWidget, QVBoxLayout, QHBoxLayout, QGridLayout,
+ QGroupBox, QLabel, QLineEdit, QComboBox, QCheckBox,
+ QPushButton, QPlainTextEdit, QListWidget, QListWidgetItem,
+ QSplitter, QFrame, QFileDialog, QMessageBox, QScrollArea,
+ QSpinBox, QTabWidget, QDateTimeEdit
+)
+from PySide6.QtCore import Qt, Signal, QDateTime
+from PySide6.QtGui import QFont
+
+from ..models.task_model import TaskItem, TaskConfig, TaskCategory, TASK_CATEGORIES, get_task_category
+from ..utils.cli_builder import CLIBuilder
+from ..utils.app_settings import app_settings
+from ..workers.task_worker import TaskWorker
+
+
+# ODS 自动更新任务(从 API 抓取)
+AUTO_UPDATE_TASKS = [
+ "ODS_PAYMENT",
+ "ODS_MEMBER",
+ "ODS_MEMBER_CARD",
+ "ODS_MEMBER_BALANCE",
+ "ODS_SETTLEMENT_RECORDS",
+ "ODS_TABLE_USE",
+ "ODS_ASSISTANT_ACCOUNT",
+ "ODS_ASSISTANT_LEDGER",
+ "ODS_ASSISTANT_ABOLISH",
+ "ODS_REFUND",
+ "ODS_PLATFORM_COUPON",
+ "ODS_RECHARGE_SETTLE",
+ "ODS_SETTLEMENT_TICKET",
+]
+
+# 数据校验相关任务
+INTEGRITY_CHECK_TASKS = [
+ "DATA_INTEGRITY_CHECK",
+]
+
+# 所有可用任务
+ALL_TASKS = [
+ # ODS 任务
+ ("ODS_PAYMENT", "支付流水", "抓取支付记录到 ODS"),
+ ("ODS_MEMBER", "会员档案", "抓取会员信息到 ODS"),
+ ("ODS_MEMBER_CARD", "会员储值卡", "抓取会员卡信息到 ODS"),
+ ("ODS_MEMBER_BALANCE", "会员余额变动", "抓取会员余额变动到 ODS"),
+ ("ODS_SETTLEMENT_RECORDS", "结账记录", "抓取结账记录到 ODS"),
+ ("ODS_TABLE_USE", "台费计费流水", "抓取台费使用记录到 ODS"),
+ ("ODS_ASSISTANT_ACCOUNT", "助教账号", "抓取助教信息到 ODS"),
+ ("ODS_ASSISTANT_LEDGER", "助教流水", "抓取助教服务流水到 ODS"),
+ ("ODS_ASSISTANT_ABOLISH", "助教作废", "抓取助教作废记录到 ODS"),
+ ("ODS_REFUND", "退款流水", "抓取退款记录到 ODS"),
+ ("ODS_PLATFORM_COUPON", "平台券核销", "抓取券核销记录到 ODS"),
+ ("ODS_RECHARGE_SETTLE", "充值结算", "抓取充值结算记录到 ODS"),
+ ("ODS_GROUP_PACKAGE", "团购套餐", "抓取团购套餐定义到 ODS"),
+ ("ODS_GROUP_BUY_REDEMPTION", "团购核销", "抓取团购核销记录到 ODS"),
+ ("ODS_INVENTORY_STOCK", "库存汇总", "抓取库存汇总到 ODS"),
+ ("ODS_INVENTORY_CHANGE", "库存变化", "抓取库存变动记录到 ODS"),
+ ("ODS_TABLES", "台桌维表", "抓取台桌信息到 ODS"),
+ ("ODS_GOODS_CATEGORY", "商品分类", "抓取商品分类到 ODS"),
+ ("ODS_STORE_GOODS", "门店商品", "抓取门店商品档案到 ODS"),
+ ("ODS_STORE_GOODS_SALES", "商品销售流水", "抓取商品销售流水到 ODS"),
+ ("ODS_TABLE_FEE_DISCOUNT", "台费折扣", "抓取台费折扣记录到 ODS"),
+ ("ODS_TENANT_GOODS", "租户商品", "抓取租户商品档案到 ODS"),
+ ("ODS_SETTLEMENT_TICKET", "结账小票", "抓取结账小票详情到 ODS"),
+ # DWD/DWS 任务
+ ("DWD_LOAD_FROM_ODS", "ODS→DWD 装载", "从 ODS 增量装载到 DWD"),
+ ("DWD_QUALITY_CHECK", "DWD 质量检查", "执行 DWD 数据质量检查"),
+ ("DWS_BUILD_ORDER_SUMMARY", "构建订单汇总", "重算 DWS 订单汇总表"),
+ # Schema 初始化
+ ("INIT_ODS_SCHEMA", "初始化 ODS Schema", "创建/重建 ODS 表结构"),
+ ("INIT_DWD_SCHEMA", "初始化 DWD Schema", "创建/重建 DWD 表结构"),
+ ("INIT_DWS_SCHEMA", "初始化 DWS Schema", "创建/重建 DWS 表结构"),
+ # 其他任务
+ ("MANUAL_INGEST", "手工数据灌入", "从本地 JSON 回放入库"),
+ ("CHECK_CUTOFF", "检查 Cutoff", "查看各表数据截止时间"),
+ ("DATA_INTEGRITY_CHECK", "数据完整性检查", "检查 ODS/DWD 数据完整性"),
+]
+
+
+class TaskPanel(QWidget):
+ """任务配置面板"""
+
+ # 信号
+ task_started = Signal(str) # 任务开始信号
+ task_finished = Signal(bool, str) # 任务完成信号 (success, message)
+ log_message = Signal(str) # 日志消息信号
+ add_to_queue = Signal(object) # 添加到队列信号 (TaskConfig)
+ create_schedule = Signal(str, list, dict) # 创建调度任务信号 (name, task_codes, task_config)
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.cli_builder = CLIBuilder()
+ self.worker = None
+ self._init_ui()
+ self._connect_signals()
+ self.refresh_tasks()
+ self._load_settings() # 启动时加载保存的设置
+
+ def _init_ui(self):
+ """初始化界面"""
+ layout = QVBoxLayout(self)
+ layout.setContentsMargins(16, 16, 16, 16)
+ layout.setSpacing(16)
+
+ # 标题
+ title = QLabel("任务配置")
+ title.setProperty("heading", True)
+ layout.addWidget(title)
+
+ # 创建分割器
+ splitter = QSplitter(Qt.Horizontal)
+ layout.addWidget(splitter, 1)
+
+ # 左侧:任务选择
+ left_widget = self._create_task_selection()
+ splitter.addWidget(left_widget)
+
+ # 右侧:参数配置
+ right_widget = self._create_config_area()
+ splitter.addWidget(right_widget)
+
+ # 设置分割比例
+ splitter.setSizes([400, 600])
+
+ # 底部:CLI 预览和执行按钮
+ bottom_widget = self._create_bottom_area()
+ layout.addWidget(bottom_widget)
+
+ def _create_task_selection(self) -> QWidget:
+ """创建任务选择区域"""
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(0, 0, 8, 0)
+
+ # 任务分类过滤
+ filter_layout = QHBoxLayout()
+ filter_layout.addWidget(QLabel("分类:"))
+ self.category_combo = QComboBox()
+ self.category_combo.addItem("全部", None)
+ self.category_combo.addItem("ODS 数据抓取", TaskCategory.ODS)
+ self.category_combo.addItem("DWD 装载", TaskCategory.DWD)
+ self.category_combo.addItem("DWS 汇总", TaskCategory.DWS)
+ self.category_combo.addItem("Schema 初始化", TaskCategory.SCHEMA)
+ self.category_combo.addItem("质量检查", TaskCategory.QUALITY)
+ self.category_combo.addItem("其他", TaskCategory.OTHER)
+ filter_layout.addWidget(self.category_combo, 1)
+ layout.addLayout(filter_layout)
+
+ # 快捷操作按钮
+ btn_layout = QHBoxLayout()
+ self.select_all_btn = QPushButton("全选")
+ self.select_all_btn.setProperty("secondary", True)
+ self.deselect_all_btn = QPushButton("全不选")
+ self.deselect_all_btn.setProperty("secondary", True)
+ btn_layout.addWidget(self.select_all_btn)
+ btn_layout.addWidget(self.deselect_all_btn)
+ layout.addLayout(btn_layout)
+
+ # 任务列表
+ self.task_list = QListWidget()
+ self.task_list.setSelectionMode(QListWidget.MultiSelection)
+ layout.addWidget(self.task_list, 1)
+
+ # 已选任务数
+ self.selected_count_label = QLabel("已选: 0 个任务")
+ self.selected_count_label.setProperty("subheading", True)
+ layout.addWidget(self.selected_count_label)
+
+ return widget
+
+ def _create_config_area(self) -> QWidget:
+ """创建参数配置区域"""
+ # 使用选项卡区分快捷操作和高级配置
+ tab_widget = QTabWidget()
+
+ # 快捷操作选项卡
+ quick_tab = self._create_quick_actions_tab()
+ tab_widget.addTab(quick_tab, "快捷操作")
+
+ # 高级配置选项卡
+ advanced_tab = self._create_advanced_config_tab()
+ tab_widget.addTab(advanced_tab, "高级配置")
+
+ return tab_widget
+
+ def _create_quick_actions_tab(self) -> QWidget:
+ """创建快捷操作选项卡"""
+ scroll_area = QScrollArea()
+ scroll_area.setWidgetResizable(True)
+ scroll_area.setFrameShape(QFrame.NoFrame)
+
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(8, 8, 8, 8)
+ layout.setSpacing(16)
+
+ # ====== 自动更新 ======
+ auto_update_group = QGroupBox("自动更新(API → ODS)")
+ auto_update_layout = QVBoxLayout(auto_update_group)
+
+ # 说明
+ desc_label = QLabel("从 API 抓取数据并更新 ODS 层,适用于日常增量更新")
+ desc_label.setProperty("subheading", True)
+ desc_label.setWordWrap(True)
+ auto_update_layout.addWidget(desc_label)
+
+ # 时间范围
+ time_layout = QHBoxLayout()
+ time_layout.addWidget(QLabel("时间范围:"))
+
+ self.auto_update_hours = QSpinBox()
+ self.auto_update_hours.setRange(1, 720) # 1小时 - 30天
+ self.auto_update_hours.setValue(24)
+ self.auto_update_hours.setSuffix(" 小时前")
+ time_layout.addWidget(self.auto_update_hours)
+
+ time_layout.addWidget(QLabel("到 当前"))
+ time_layout.addStretch()
+ auto_update_layout.addLayout(time_layout)
+
+ # 冗余窗口
+ overlap_layout = QHBoxLayout()
+ overlap_layout.addWidget(QLabel("冗余窗口:"))
+ self.overlap_seconds = QSpinBox()
+ self.overlap_seconds.setRange(0, 7200)
+ self.overlap_seconds.setValue(3600)
+ self.overlap_seconds.setSuffix(" 秒")
+ self.overlap_seconds.setToolTip("向前多抓取的时间,避免边界数据丢失")
+ overlap_layout.addWidget(self.overlap_seconds)
+ overlap_layout.addStretch()
+ auto_update_layout.addLayout(overlap_layout)
+
+ # 任务选择
+ task_header_layout = QHBoxLayout()
+ task_label = QLabel("包含任务:")
+ task_header_layout.addWidget(task_label)
+ task_header_layout.addStretch()
+
+ self.auto_update_select_all_btn = QPushButton("全选")
+ self.auto_update_select_all_btn.setProperty("secondary", True)
+ self.auto_update_select_all_btn.setFixedWidth(60)
+ task_header_layout.addWidget(self.auto_update_select_all_btn)
+
+ self.auto_update_deselect_all_btn = QPushButton("全不选")
+ self.auto_update_deselect_all_btn.setProperty("secondary", True)
+ self.auto_update_deselect_all_btn.setFixedWidth(60)
+ task_header_layout.addWidget(self.auto_update_deselect_all_btn)
+
+ auto_update_layout.addLayout(task_header_layout)
+
+ self.auto_update_tasks_list = QListWidget()
+ self.auto_update_tasks_list.setSelectionMode(QListWidget.MultiSelection)
+ self.auto_update_tasks_list.setMaximumHeight(150)
+ for task_code in AUTO_UPDATE_TASKS:
+ item = QListWidgetItem(task_code)
+ item.setSelected(True) # 默认全选
+ self.auto_update_tasks_list.addItem(item)
+ auto_update_layout.addWidget(self.auto_update_tasks_list)
+
+ # 包含 DWD 装载
+ self.include_dwd_check = QCheckBox("完成后执行 DWD 装载 (ODS → DWD)")
+ self.include_dwd_check.setChecked(True)
+ auto_update_layout.addWidget(self.include_dwd_check)
+
+ # 自动校验
+ self.auto_verify_check = QCheckBox("完成后执行数据校验")
+ self.auto_verify_check.setToolTip("ETL 导入完成后,自动执行数据完整性校验")
+ self.auto_verify_check.setChecked(False)
+ auto_update_layout.addWidget(self.auto_verify_check)
+
+ # 操作按钮
+ auto_btn_layout = QHBoxLayout()
+ auto_btn_layout.addStretch()
+
+ self.auto_update_run_btn = QPushButton("立即执行一次")
+ self.auto_update_run_btn.setToolTip("添加到任务队列并立即执行")
+ auto_btn_layout.addWidget(self.auto_update_run_btn)
+
+ self.auto_update_schedule_btn = QPushButton("创建调度任务")
+ self.auto_update_schedule_btn.setToolTip("添加到定时调度中,可设置执行周期")
+ auto_btn_layout.addWidget(self.auto_update_schedule_btn)
+
+ auto_update_layout.addLayout(auto_btn_layout)
+
+ layout.addWidget(auto_update_group)
+
+ # ====== 数据校验 ======
+ integrity_group = QGroupBox("数据校验(API vs ODS)")
+ integrity_layout = QVBoxLayout(integrity_group)
+
+ # 说明
+ int_desc = QLabel("对比 API 数据与 ODS 数据,检查是否有缺失或不一致")
+ int_desc.setProperty("subheading", True)
+ int_desc.setWordWrap(True)
+ integrity_layout.addWidget(int_desc)
+
+ # 校验模式
+ mode_layout = QHBoxLayout()
+ mode_layout.addWidget(QLabel("校验模式:"))
+ self.integrity_mode_combo = QComboBox()
+ self.integrity_mode_combo.addItem("历史全量校验", "history")
+ self.integrity_mode_combo.addItem("最近增量校验", "recent")
+ mode_layout.addWidget(self.integrity_mode_combo, 1)
+ integrity_layout.addLayout(mode_layout)
+
+ # 时间范围 - 历史模式
+ self.history_range_widget = QWidget()
+ history_layout = QGridLayout(self.history_range_widget)
+ history_layout.setContentsMargins(0, 0, 0, 0)
+
+ history_layout.addWidget(QLabel("开始日期:"), 0, 0)
+ self.integrity_start_date = QDateTimeEdit()
+ self.integrity_start_date.setDisplayFormat("yyyy-MM-dd")
+ self.integrity_start_date.setCalendarPopup(True)
+ self.integrity_start_date.setDateTime(QDateTime.currentDateTime().addMonths(-6))
+ history_layout.addWidget(self.integrity_start_date, 0, 1)
+
+ history_layout.addWidget(QLabel("结束日期:"), 1, 0)
+ self.integrity_end_date = QDateTimeEdit()
+ self.integrity_end_date.setDisplayFormat("yyyy-MM-dd")
+ self.integrity_end_date.setCalendarPopup(True)
+ self.integrity_end_date.setDateTime(QDateTime.currentDateTime())
+ history_layout.addWidget(self.integrity_end_date, 1, 1)
+
+ integrity_layout.addWidget(self.history_range_widget)
+
+ # 时间范围 - 最近模式
+ self.recent_range_widget = QWidget()
+ recent_layout = QHBoxLayout(self.recent_range_widget)
+ recent_layout.setContentsMargins(0, 0, 0, 0)
+ recent_layout.addWidget(QLabel("回溯时间:"))
+ self.integrity_hours = QSpinBox()
+ self.integrity_hours.setRange(1, 168) # 1小时 - 7天
+ self.integrity_hours.setValue(24)
+ self.integrity_hours.setSuffix(" 小时")
+ recent_layout.addWidget(self.integrity_hours)
+ recent_layout.addStretch()
+ self.recent_range_widget.setVisible(False)
+ integrity_layout.addWidget(self.recent_range_widget)
+
+ # 校验选项
+ self.include_dimensions_check = QCheckBox("包含维度表校验")
+ integrity_layout.addWidget(self.include_dimensions_check)
+
+ # 自动补全选项
+ self.auto_backfill_check = QCheckBox("校验后自动补全丢失数据")
+ self.auto_backfill_check.setToolTip("如果发现丢失数据,自动从 API 重新获取并补全到 ODS")
+ integrity_layout.addWidget(self.auto_backfill_check)
+
+ # 指定 ODS 任务
+ ods_task_layout = QHBoxLayout()
+ ods_task_layout.addWidget(QLabel("指定任务 (可选):"))
+ self.integrity_ods_tasks = QLineEdit()
+ self.integrity_ods_tasks.setPlaceholderText("例: ODS_PAYMENT,ODS_MEMBER (留空=全部)")
+ ods_task_layout.addWidget(self.integrity_ods_tasks, 1)
+ integrity_layout.addLayout(ods_task_layout)
+
+ # 操作按钮
+ int_btn_layout = QHBoxLayout()
+ int_btn_layout.addStretch()
+
+ self.integrity_run_btn = QPushButton("立即执行一次")
+ self.integrity_run_btn.setToolTip("添加到任务队列并立即执行")
+ int_btn_layout.addWidget(self.integrity_run_btn)
+
+ self.integrity_schedule_btn = QPushButton("创建调度任务")
+ self.integrity_schedule_btn.setToolTip("添加到定时调度中,可设置执行周期")
+ int_btn_layout.addWidget(self.integrity_schedule_btn)
+
+ integrity_layout.addLayout(int_btn_layout)
+
+ layout.addWidget(integrity_group)
+
+ # 弹性空间
+ layout.addStretch()
+
+ scroll_area.setWidget(widget)
+ return scroll_area
+
+ def _create_advanced_config_tab(self) -> QWidget:
+ """创建高级配置选项卡"""
+ scroll_area = QScrollArea()
+ scroll_area.setWidgetResizable(True)
+ scroll_area.setFrameShape(QFrame.NoFrame)
+
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(8, 8, 8, 8)
+
+ # Pipeline 流程配置
+ pipeline_group = QGroupBox("流水线配置")
+ pipeline_layout = QGridLayout(pipeline_group)
+
+ pipeline_layout.addWidget(QLabel("运行模式:"), 0, 0)
+ self.pipeline_flow_combo = QComboBox()
+ self.pipeline_flow_combo.addItem("FULL - 在线抓取 + 入库", "FULL")
+ self.pipeline_flow_combo.addItem("FETCH_ONLY - 仅在线抓取落盘", "FETCH_ONLY")
+ self.pipeline_flow_combo.addItem("INGEST_ONLY - 仅本地 JSON 入库", "INGEST_ONLY")
+ pipeline_layout.addWidget(self.pipeline_flow_combo, 0, 1)
+
+ self.dry_run_check = QCheckBox("Dry-run 模式(不提交数据库)")
+ pipeline_layout.addWidget(self.dry_run_check, 1, 0, 1, 2)
+
+ layout.addWidget(pipeline_group)
+
+ # 时间窗口配置
+ window_group = QGroupBox("时间窗口(可选)")
+ window_layout = QGridLayout(window_group)
+
+ window_layout.addWidget(QLabel("开始时间:"), 0, 0)
+ self.window_start_edit = QLineEdit()
+ self.window_start_edit.setPlaceholderText("例: 2025-07-01 00:00:00")
+ window_layout.addWidget(self.window_start_edit, 0, 1)
+
+ window_layout.addWidget(QLabel("结束时间:"), 1, 0)
+ self.window_end_edit = QLineEdit()
+ self.window_end_edit.setPlaceholderText("例: 2025-08-01 00:00:00")
+ window_layout.addWidget(self.window_end_edit, 1, 1)
+
+ # 窗口切分选项
+ window_layout.addWidget(QLabel("切分模式:"), 2, 0)
+ self.window_split_combo = QComboBox()
+ self.window_split_combo.addItem("不切分", "none")
+ self.window_split_combo.addItem("按月切分", "month")
+ self.window_split_combo.setToolTip("长时间窗口按月切分执行,避免单次请求过大")
+ window_layout.addWidget(self.window_split_combo, 2, 1)
+
+ window_layout.addWidget(QLabel("补偿小时:"), 3, 0)
+ self.window_compensation_spin = QSpinBox()
+ self.window_compensation_spin.setRange(0, 168) # 最多7天
+ self.window_compensation_spin.setValue(0)
+ self.window_compensation_spin.setSuffix(" 小时")
+ self.window_compensation_spin.setToolTip("窗口前后扩展的小时数,用于捕获边界数据")
+ window_layout.addWidget(self.window_compensation_spin, 3, 1)
+
+ layout.addWidget(window_group)
+
+ # 数据源配置
+ source_group = QGroupBox("数据源配置(INGEST_ONLY 模式)")
+ source_layout = QGridLayout(source_group)
+
+ source_layout.addWidget(QLabel("JSON 目录:"), 0, 0)
+ self.ingest_source_edit = QLineEdit()
+ self.ingest_source_edit.setPlaceholderText("本地 JSON 文件目录")
+ source_layout.addWidget(self.ingest_source_edit, 0, 1)
+
+ self.browse_btn = QPushButton("浏览...")
+ self.browse_btn.setProperty("secondary", True)
+ source_layout.addWidget(self.browse_btn, 0, 2)
+
+ layout.addWidget(source_group)
+
+ # 覆盖配置(高级)
+ override_group = QGroupBox("覆盖配置(可选)")
+ override_layout = QGridLayout(override_group)
+
+ override_layout.addWidget(QLabel("门店 ID:"), 0, 0)
+ self.store_id_edit = QLineEdit()
+ self.store_id_edit.setPlaceholderText("使用 .env 中的配置")
+ override_layout.addWidget(self.store_id_edit, 0, 1)
+
+ override_layout.addWidget(QLabel("数据库 DSN:"), 1, 0)
+ self.pg_dsn_edit = QLineEdit()
+ self.pg_dsn_edit.setPlaceholderText("使用 .env 中的配置")
+ override_layout.addWidget(self.pg_dsn_edit, 1, 1)
+
+ override_layout.addWidget(QLabel("API Token:"), 2, 0)
+ self.api_token_edit = QLineEdit()
+ self.api_token_edit.setPlaceholderText("使用 .env 中的配置")
+ self.api_token_edit.setEchoMode(QLineEdit.Password)
+ override_layout.addWidget(self.api_token_edit, 2, 1)
+
+ layout.addWidget(override_group)
+
+ # 弹性空间
+ layout.addStretch()
+
+ scroll_area.setWidget(widget)
+ return scroll_area
+
+ def _create_bottom_area(self) -> QWidget:
+ """创建底部区域"""
+ widget = QWidget()
+ layout = QVBoxLayout(widget)
+ layout.setContentsMargins(0, 0, 0, 0)
+
+ # CLI 预览
+ preview_group = QGroupBox("命令行预览")
+ preview_layout = QVBoxLayout(preview_group)
+
+ self.cli_preview = QPlainTextEdit()
+ self.cli_preview.setReadOnly(True)
+ self.cli_preview.setMaximumHeight(80)
+ self.cli_preview.setFont(QFont("Consolas", 10))
+ preview_layout.addWidget(self.cli_preview)
+
+ layout.addWidget(preview_group)
+
+ # 执行按钮
+ btn_layout = QHBoxLayout()
+ btn_layout.addStretch()
+
+ self.add_to_queue_btn = QPushButton("添加到队列")
+ self.add_to_queue_btn.setProperty("secondary", True)
+ btn_layout.addWidget(self.add_to_queue_btn)
+
+ self.run_btn = QPushButton("立即执行")
+ self.run_btn.setFixedWidth(120)
+ btn_layout.addWidget(self.run_btn)
+
+ self.stop_btn = QPushButton("停止")
+ self.stop_btn.setProperty("danger", True)
+ self.stop_btn.setEnabled(False)
+ self.stop_btn.setFixedWidth(80)
+ btn_layout.addWidget(self.stop_btn)
+
+ layout.addLayout(btn_layout)
+
+ return widget
+
+ def _connect_signals(self):
+ """连接信号"""
+ # 分类过滤
+ self.category_combo.currentIndexChanged.connect(self._filter_tasks)
+
+ # 任务选择
+ self.task_list.itemSelectionChanged.connect(self._on_selection_changed)
+ self.select_all_btn.clicked.connect(self._select_all)
+ self.deselect_all_btn.clicked.connect(self._deselect_all)
+
+ # 配置变化
+ self.pipeline_flow_combo.currentIndexChanged.connect(self._update_preview)
+ self.dry_run_check.stateChanged.connect(self._update_preview)
+ self.window_start_edit.textChanged.connect(self._update_preview)
+ self.window_end_edit.textChanged.connect(self._update_preview)
+ self.ingest_source_edit.textChanged.connect(self._update_preview)
+ self.store_id_edit.textChanged.connect(self._update_preview)
+ self.pg_dsn_edit.textChanged.connect(self._update_preview)
+ self.api_token_edit.textChanged.connect(self._update_preview)
+
+ # 浏览目录
+ self.browse_btn.clicked.connect(self._browse_source_dir)
+
+ # 执行按钮
+ self.run_btn.clicked.connect(self._run_task)
+ self.stop_btn.clicked.connect(self._stop_task)
+ self.add_to_queue_btn.clicked.connect(self._add_task_to_queue)
+
+ # 快捷操作 - 自动更新
+ self.auto_update_run_btn.clicked.connect(self._run_auto_update_now)
+ self.auto_update_schedule_btn.clicked.connect(self._create_auto_update_schedule)
+ self.auto_update_select_all_btn.clicked.connect(self._auto_update_select_all)
+ self.auto_update_deselect_all_btn.clicked.connect(self._auto_update_deselect_all)
+
+ # 快捷操作 - 数据校验
+ self.integrity_run_btn.clicked.connect(self._run_integrity_check_now)
+ self.integrity_schedule_btn.clicked.connect(self._create_integrity_schedule)
+ self.integrity_mode_combo.currentIndexChanged.connect(self._on_integrity_mode_changed)
+
+ # 保存设置的信号连接
+ self.auto_update_hours.valueChanged.connect(self._save_auto_update_settings)
+ self.overlap_seconds.valueChanged.connect(self._save_auto_update_settings)
+ self.include_dwd_check.stateChanged.connect(self._save_auto_update_settings)
+ self.auto_verify_check.stateChanged.connect(self._save_auto_update_settings)
+ self.integrity_mode_combo.currentIndexChanged.connect(self._save_integrity_settings)
+ self.integrity_start_date.dateTimeChanged.connect(self._save_integrity_settings)
+ self.integrity_end_date.dateTimeChanged.connect(self._save_integrity_settings)
+ self.integrity_hours.valueChanged.connect(self._save_integrity_settings)
+ self.include_dimensions_check.stateChanged.connect(self._save_integrity_settings)
+ self.auto_backfill_check.stateChanged.connect(self._save_integrity_settings)
+ self.integrity_ods_tasks.textChanged.connect(self._save_integrity_settings)
+ self.pipeline_flow_combo.currentIndexChanged.connect(self._save_advanced_settings)
+ self.dry_run_check.stateChanged.connect(self._save_advanced_settings)
+ self.window_split_combo.currentIndexChanged.connect(self._save_advanced_settings)
+ self.window_compensation_spin.valueChanged.connect(self._save_advanced_settings)
+
+ def refresh_tasks(self):
+ """刷新任务列表"""
+ self.task_list.clear()
+
+ current_category = self.category_combo.currentData()
+
+ for code, name, desc in ALL_TASKS:
+ category = get_task_category(code)
+
+ # 应用分类过滤
+ if current_category is not None and category != current_category:
+ continue
+
+ item = QListWidgetItem(f"{name} ({code})")
+ item.setData(Qt.UserRole, code)
+ item.setToolTip(desc)
+ self.task_list.addItem(item)
+
+ self._on_selection_changed()
+
+ def _filter_tasks(self):
+ """过滤任务列表"""
+ self.refresh_tasks()
+
+ def _on_selection_changed(self):
+ """选择变化时"""
+ selected = self.task_list.selectedItems()
+ self.selected_count_label.setText(f"已选: {len(selected)} 个任务")
+ self._update_preview()
+
+ def _select_all(self):
+ """全选"""
+ self.task_list.selectAll()
+
+ def _deselect_all(self):
+ """全不选"""
+ self.task_list.clearSelection()
+
+ def _browse_source_dir(self):
+ """浏览数据源目录"""
+ dir_path = QFileDialog.getExistingDirectory(
+ self, "选择 JSON 数据目录"
+ )
+ if dir_path:
+ self.ingest_source_edit.setText(dir_path)
+
+ def _get_config(self) -> TaskConfig:
+ """获取当前配置"""
+ # 获取选中的任务
+ selected_tasks = []
+ for item in self.task_list.selectedItems():
+ task_code = item.data(Qt.UserRole)
+ if task_code:
+ selected_tasks.append(task_code)
+
+ # 构建环境变量(窗口切分参数)
+ env_vars = {}
+ split_unit = self.window_split_combo.currentData() or "none"
+ compensation = self.window_compensation_spin.value()
+ if split_unit and split_unit != "none":
+ env_vars["WINDOW_SPLIT_UNIT"] = split_unit
+ if compensation > 0:
+ env_vars["WINDOW_COMPENSATION_HOURS"] = str(compensation)
+
+ # 构建配置
+ config = TaskConfig(
+ tasks=selected_tasks,
+ pipeline_flow=self.pipeline_flow_combo.currentData(),
+ dry_run=self.dry_run_check.isChecked(),
+ window_start=self.window_start_edit.text().strip() or None,
+ window_end=self.window_end_edit.text().strip() or None,
+ window_split=split_unit,
+ window_compensation=compensation,
+ ingest_source=self.ingest_source_edit.text().strip() or None,
+ store_id=int(self.store_id_edit.text()) if self.store_id_edit.text().strip().isdigit() else None,
+ pg_dsn=self.pg_dsn_edit.text().strip() or None,
+ api_token=self.api_token_edit.text().strip() or None,
+ env_vars=env_vars,
+ )
+
+ return config
+
+ def _update_preview(self):
+ """更新命令行预览"""
+ config = self._get_config()
+ cmd_str = self.cli_builder.build_command_string(config)
+ self.cli_preview.setPlainText(cmd_str)
+
+ def _run_task(self):
+ """执行任务"""
+ config = self._get_config()
+
+ if not config.tasks:
+ QMessageBox.warning(self, "提示", "请至少选择一个任务")
+ return
+
+ # 创建工作线程
+ cmd = self.cli_builder.build_command(config)
+ self.worker = TaskWorker(cmd)
+
+ # 连接信号
+ self.worker.output_received.connect(self._on_output)
+ self.worker.task_finished.connect(self._on_finished)
+ self.worker.error_occurred.connect(self._on_error)
+
+ # 更新 UI 状态
+ self.run_btn.setEnabled(False)
+ self.stop_btn.setEnabled(True)
+
+ # 发送开始信号
+ task_info = ",".join(config.tasks[:3])
+ if len(config.tasks) > 3:
+ task_info += f" 等{len(config.tasks)}个任务"
+ self.task_started.emit(task_info)
+
+ # 启动
+ self.worker.start()
+
+ def _stop_task(self):
+ """停止任务"""
+ if self.worker and self.worker.isRunning():
+ self.worker.stop()
+ self.log_message.emit("[GUI] 正在停止任务...")
+
+ def _on_output(self, line: str):
+ """收到输出"""
+ self.log_message.emit(line)
+
+ def _on_finished(self, exit_code: int, summary: str):
+ """任务完成"""
+ self.run_btn.setEnabled(True)
+ self.stop_btn.setEnabled(False)
+
+ success = exit_code == 0
+ message = summary if summary else ("任务执行成功" if success else f"任务执行失败 (exit={exit_code})")
+ self.task_finished.emit(success, message)
+
+ if success:
+ self.log_message.emit(f"[GUI] 任务完成: {message}")
+ else:
+ self.log_message.emit(f"[GUI] 任务失败: {message}")
+
+ def _on_error(self, error: str):
+ """发生错误"""
+ self.log_message.emit(f"[GUI] 错误: {error}")
+ QMessageBox.critical(self, "执行错误", error)
+
+ def is_running(self) -> bool:
+ """是否正在执行任务"""
+ return self.worker is not None and self.worker.isRunning()
+
+ def _add_task_to_queue(self):
+ """将任务列表中选中的任务添加到队列"""
+ config = self._get_config()
+
+ if not config.tasks:
+ QMessageBox.warning(self, "提示", "请至少选择一个任务")
+ return
+
+ # 发送信号添加到队列
+ self.add_to_queue.emit(config)
+
+ task_info = ",".join(config.tasks[:3])
+ if len(config.tasks) > 3:
+ task_info += f" 等{len(config.tasks)}个"
+
+ self.log_message.emit(f"[GUI] 已添加到任务队列: {task_info}")
+ QMessageBox.information(self, "提示", f"已添加到任务队列\n\n任务: {task_info}\n\n请切换到「任务管理」查看和执行")
+
+ def _on_integrity_mode_changed(self, index: int):
+ """校验模式变化"""
+ mode = self.integrity_mode_combo.currentData()
+ self.history_range_widget.setVisible(mode == "history")
+ self.recent_range_widget.setVisible(mode == "recent")
+
+ def _auto_update_select_all(self):
+ """自动更新任务列表全选"""
+ self.auto_update_tasks_list.selectAll()
+ self._save_auto_update_settings()
+
+ def _auto_update_deselect_all(self):
+ """自动更新任务列表全不选"""
+ self.auto_update_tasks_list.clearSelection()
+ self._save_auto_update_settings()
+
+ def _get_auto_update_tasks(self) -> list:
+ """获取自动更新选中的任务"""
+ selected_tasks = []
+ for i in range(self.auto_update_tasks_list.count()):
+ item = self.auto_update_tasks_list.item(i)
+ if item.isSelected():
+ selected_tasks.append(item.text())
+
+ if self.include_dwd_check.isChecked():
+ selected_tasks.append("DWD_LOAD_FROM_ODS")
+
+ return selected_tasks
+
+ def _get_auto_update_config(self) -> dict:
+ """获取自动更新配置"""
+ return {
+ "pipeline_flow": "FULL",
+ "lookback_hours": self.auto_update_hours.value(),
+ "overlap_seconds": self.overlap_seconds.value(),
+ }
+
+ def _run_auto_update_now(self):
+ """立即执行自动更新(添加到队列)"""
+ selected_tasks = self._get_auto_update_tasks()
+
+ if not selected_tasks:
+ QMessageBox.warning(self, "提示", "请至少选择一个任务")
+ return
+
+ hours = self.auto_update_hours.value()
+ overlap = self.overlap_seconds.value()
+ include_dwd = self.include_dwd_check.isChecked()
+ auto_verify = self.auto_verify_check.isChecked()
+
+ now = datetime.now()
+ start_time = now - timedelta(hours=hours, seconds=overlap)
+
+ # 构建完整任务列表
+ all_tasks = selected_tasks.copy()
+
+ # 添加 DWD 装载
+ if include_dwd and "DWD_LOAD_FROM_ODS" not in all_tasks:
+ all_tasks.append("DWD_LOAD_FROM_ODS")
+
+ # 添加数据校验
+ if auto_verify and "DATA_INTEGRITY_CHECK" not in all_tasks:
+ all_tasks.append("DATA_INTEGRITY_CHECK")
+
+ # 构建环境变量(用于校验任务)
+ env_vars = {}
+ if auto_verify:
+ env_vars["INTEGRITY_MODE"] = "window"
+ env_vars["INTEGRITY_AUTO_BACKFILL"] = "1" # 自动补全丢失数据
+
+ config = TaskConfig(
+ tasks=all_tasks,
+ pipeline_flow="FULL",
+ window_start=start_time.strftime("%Y-%m-%d %H:%M:%S"),
+ window_end=now.strftime("%Y-%m-%d %H:%M:%S"),
+ env_vars=env_vars,
+ )
+
+ # 更新预览
+ cmd_str = self.cli_builder.build_command_string(config)
+ self.cli_preview.setPlainText(cmd_str)
+
+ # 构建任务描述
+ desc_parts = [f"自动更新 ({hours}h)"]
+ if include_dwd:
+ desc_parts.append("+ DWD")
+ if auto_verify:
+ desc_parts.append("+ 校验")
+ task_desc = " ".join(desc_parts)
+
+ # 发送信号添加到队列
+ self.add_to_queue.emit(config)
+ self.log_message.emit(f"[GUI] 已添加到任务队列: {task_desc}")
+ QMessageBox.information(self, "提示", f"已添加到任务队列\n\n任务: {task_desc}\n包含: {len(all_tasks)} 个任务\n\n请切换到「任务管理」查看和执行")
+
+ def _create_auto_update_schedule(self):
+ """创建自动更新的调度任务"""
+ selected_tasks = self._get_auto_update_tasks()
+
+ if not selected_tasks:
+ QMessageBox.warning(self, "提示", "请至少选择一个任务")
+ return
+
+ hours = self.auto_update_hours.value()
+ task_config = self._get_auto_update_config()
+
+ # 发送信号创建调度任务
+ self.create_schedule.emit(
+ f"自动更新 ({hours}h)",
+ selected_tasks,
+ task_config
+ )
+ self.log_message.emit(f"[GUI] 创建调度任务: 自动更新 ({hours}h)")
+
+ def _get_integrity_config(self) -> dict:
+ """获取数据校验配置"""
+ mode = self.integrity_mode_combo.currentData()
+
+ config = {
+ "pipeline_flow": "INGEST_ONLY",
+ "integrity_mode": mode,
+ "integrity_include_dimensions": self.include_dimensions_check.isChecked(),
+ "integrity_auto_backfill": self.auto_backfill_check.isChecked(),
+ }
+
+ if mode == "history":
+ config["integrity_history_start"] = self.integrity_start_date.dateTime().toString("yyyy-MM-dd")
+ config["integrity_history_end"] = self.integrity_end_date.dateTime().toString("yyyy-MM-dd")
+ else:
+ config["lookback_hours"] = self.integrity_hours.value()
+
+ ods_tasks = self.integrity_ods_tasks.text().strip()
+ if ods_tasks:
+ config["integrity_ods_task_codes"] = ods_tasks
+
+ return config
+
+ def _run_integrity_check_now(self):
+ """立即执行数据校验(添加到队列)"""
+ mode = self.integrity_mode_combo.currentData()
+ int_config = self._get_integrity_config()
+
+ # 通过环境变量传递 integrity 配置(CLI 不支持这些参数)
+ env_vars = {
+ "INTEGRITY_MODE": int_config.get("integrity_mode", "history"),
+ "INTEGRITY_INCLUDE_DIMENSIONS": "1" if int_config.get("integrity_include_dimensions") else "0",
+ "INTEGRITY_AUTO_BACKFILL": "1" if int_config.get("integrity_auto_backfill") else "0",
+ }
+
+ if mode == "history":
+ env_vars["INTEGRITY_HISTORY_START"] = int_config.get("integrity_history_start")
+ env_vars["INTEGRITY_HISTORY_END"] = int_config.get("integrity_history_end")
+ desc = f"数据校验 ({int_config.get('integrity_history_start')} ~ {int_config.get('integrity_history_end')})"
+ else:
+ hours = int_config.get("lookback_hours", 24)
+ now = datetime.now()
+ start_time = now - timedelta(hours=hours)
+ env_vars["INTEGRITY_HISTORY_START"] = start_time.strftime("%Y-%m-%d")
+ env_vars["INTEGRITY_HISTORY_END"] = now.strftime("%Y-%m-%d")
+ desc = f"数据校验 (最近 {hours}h)"
+
+ if int_config.get("integrity_ods_task_codes"):
+ env_vars["INTEGRITY_ODS_TASK_CODES"] = int_config.get("integrity_ods_task_codes")
+
+ if int_config.get("integrity_auto_backfill"):
+ desc += " + 自动补全"
+
+ config = TaskConfig(
+ tasks=["DATA_INTEGRITY_CHECK"],
+ pipeline_flow="FULL", # 使用 FULL 因为需要 DB 连接
+ env_vars=env_vars,
+ )
+
+ # 更新预览
+ cmd_str = self.cli_builder.build_command_string(config)
+ self.cli_preview.setPlainText(cmd_str + f"\n\n# 环境变量:\n" + "\n".join(f"# {k}={v}" for k, v in env_vars.items()))
+
+ # 发送信号添加到队列
+ self.add_to_queue.emit(config)
+ self.log_message.emit(f"[GUI] 已添加到任务队列: {desc}")
+ QMessageBox.information(self, "提示", f"已添加到任务队列\n\n任务: {desc}\n\n请切换到「任务管理」查看和执行")
+
+ def _create_integrity_schedule(self):
+ """创建数据校验的调度任务"""
+ mode = self.integrity_mode_combo.currentData()
+ task_config = self._get_integrity_config()
+
+ if mode == "history":
+ desc = f"数据校验 ({task_config.get('integrity_history_start')} ~ {task_config.get('integrity_history_end')})"
+ else:
+ hours = task_config.get("lookback_hours", 24)
+ desc = f"数据校验 (最近 {hours}h)"
+
+ # 发送信号创建调度任务
+ self.create_schedule.emit(
+ desc,
+ ["DATA_INTEGRITY_CHECK"],
+ task_config
+ )
+ self.log_message.emit(f"[GUI] 创建调度任务: {desc}")
+
+ # ==================== 设置持久化 ====================
+
+ def _load_settings(self):
+ """从持久化存储加载设置"""
+ try:
+ # 加载自动更新设置
+ self.auto_update_hours.setValue(app_settings.auto_update_hours)
+ self.overlap_seconds.setValue(app_settings.auto_update_overlap_seconds)
+ self.include_dwd_check.setChecked(app_settings.auto_update_include_dwd)
+ self.auto_verify_check.setChecked(app_settings.auto_update_auto_verify)
+
+ # 恢复自动更新任务选择
+ saved_tasks = app_settings.auto_update_selected_tasks
+ if saved_tasks:
+ for i in range(self.auto_update_tasks_list.count()):
+ item = self.auto_update_tasks_list.item(i)
+ item.setSelected(item.text() in saved_tasks)
+
+ # 加载数据校验设置
+ mode = app_settings.integrity_mode
+ mode_index = 0 if mode == "history" else 1
+ self.integrity_mode_combo.setCurrentIndex(mode_index)
+
+ # 历史日期
+ if app_settings.integrity_history_start:
+ try:
+ start_date = QDateTime.fromString(app_settings.integrity_history_start, "yyyy-MM-dd")
+ if start_date.isValid():
+ self.integrity_start_date.setDateTime(start_date)
+ except Exception:
+ pass
+
+ if app_settings.integrity_history_end:
+ try:
+ end_date = QDateTime.fromString(app_settings.integrity_history_end, "yyyy-MM-dd")
+ if end_date.isValid():
+ self.integrity_end_date.setDateTime(end_date)
+ except Exception:
+ pass
+
+ self.integrity_hours.setValue(app_settings.integrity_lookback_hours)
+ self.include_dimensions_check.setChecked(app_settings.integrity_include_dimensions)
+ self.auto_backfill_check.setChecked(app_settings.integrity_auto_backfill)
+ self.integrity_ods_tasks.setText(app_settings.integrity_ods_tasks)
+
+ # 加载高级设置
+ pipeline_flow = app_settings.advanced_pipeline_flow
+ flow_map = {"FULL": 0, "FETCH_ONLY": 1, "INGEST_ONLY": 2}
+ self.pipeline_flow_combo.setCurrentIndex(flow_map.get(pipeline_flow, 0))
+ self.dry_run_check.setChecked(app_settings.advanced_dry_run)
+ self.window_start_edit.setText(app_settings.advanced_window_start)
+ self.window_end_edit.setText(app_settings.advanced_window_end)
+ self.ingest_source_edit.setText(app_settings.advanced_ingest_source)
+
+ # 加载窗口切分设置
+ split_map = {"none": 0, "month": 1}
+ self.window_split_combo.setCurrentIndex(split_map.get(app_settings.advanced_window_split, 0))
+ self.window_compensation_spin.setValue(app_settings.advanced_window_compensation)
+
+ # 更新 UI 状态
+ self._on_integrity_mode_changed(mode_index)
+
+ except Exception as e:
+ # 加载失败时不影响程序运行
+ print(f"加载设置失败: {e}")
+
+ def _save_auto_update_settings(self):
+ """保存自动更新设置"""
+ try:
+ app_settings.auto_update_hours = self.auto_update_hours.value()
+ app_settings.auto_update_overlap_seconds = self.overlap_seconds.value()
+ app_settings.auto_update_include_dwd = self.include_dwd_check.isChecked()
+ app_settings.auto_update_auto_verify = self.auto_verify_check.isChecked()
+
+ # 保存选中的任务
+ selected_tasks = []
+ for i in range(self.auto_update_tasks_list.count()):
+ item = self.auto_update_tasks_list.item(i)
+ if item.isSelected():
+ selected_tasks.append(item.text())
+ app_settings.auto_update_selected_tasks = selected_tasks
+ except Exception as e:
+ print(f"保存自动更新设置失败: {e}")
+
+ def _save_integrity_settings(self):
+ """保存数据校验设置"""
+ try:
+ mode = self.integrity_mode_combo.currentData()
+ app_settings.integrity_mode = mode or "history"
+ app_settings.integrity_history_start = self.integrity_start_date.dateTime().toString("yyyy-MM-dd")
+ app_settings.integrity_history_end = self.integrity_end_date.dateTime().toString("yyyy-MM-dd")
+ app_settings.integrity_lookback_hours = self.integrity_hours.value()
+ app_settings.integrity_include_dimensions = self.include_dimensions_check.isChecked()
+ app_settings.integrity_auto_backfill = self.auto_backfill_check.isChecked()
+ app_settings.integrity_ods_tasks = self.integrity_ods_tasks.text().strip()
+ except Exception as e:
+ print(f"保存数据校验设置失败: {e}")
+
+ def _save_advanced_settings(self):
+ """保存高级设置"""
+ try:
+ app_settings.advanced_pipeline_flow = self.pipeline_flow_combo.currentData() or "FULL"
+ app_settings.advanced_dry_run = self.dry_run_check.isChecked()
+ app_settings.advanced_window_start = self.window_start_edit.text().strip()
+ app_settings.advanced_window_end = self.window_end_edit.text().strip()
+ app_settings.advanced_ingest_source = self.ingest_source_edit.text().strip()
+ app_settings.advanced_window_split = self.window_split_combo.currentData() or "none"
+ app_settings.advanced_window_compensation = self.window_compensation_spin.value()
+ except Exception as e:
+ print(f"保存高级设置失败: {e}")
diff --git a/etl_billiards/gui/workers/__init__.py b/etl_billiards/gui/workers/__init__.py
new file mode 100644
index 0000000..f321e9f
--- /dev/null
+++ b/etl_billiards/gui/workers/__init__.py
@@ -0,0 +1,7 @@
+# -*- coding: utf-8 -*-
+"""后台工作线程模块"""
+
+from .task_worker import TaskWorker
+from .db_worker import DBWorker
+
+__all__ = ["TaskWorker", "DBWorker"]
diff --git a/etl_billiards/gui/workers/db_worker.py b/etl_billiards/gui/workers/db_worker.py
new file mode 100644
index 0000000..8d6476a
--- /dev/null
+++ b/etl_billiards/gui/workers/db_worker.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""数据库查询工作线程"""
+
+import sys
+from pathlib import Path
+from typing import List, Dict, Any, Optional, Tuple
+
+from PySide6.QtCore import QThread, Signal
+
+# 添加项目路径
+PROJECT_ROOT = Path(__file__).resolve().parents[2]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+
+class DBWorker(QThread):
+ """数据库查询工作线程"""
+
+ # 信号
+ query_finished = Signal(list, list) # 查询完成 (columns, rows)
+ query_error = Signal(str) # 查询错误
+ connection_status = Signal(bool, str) # 连接状态 (connected, message)
+ tables_loaded = Signal(dict) # 表列表加载完成 {schema: [(table, rows, updated_at), ...]}
+
+ def __init__(self, parent=None):
+ super().__init__(parent)
+ self.conn = None
+ self._task = None
+ self._task_args = None
+
+ def connect_db(self, dsn: str):
+ """连接数据库"""
+ self._task = "connect"
+ self._task_args = (dsn,)
+ self.start()
+
+ def disconnect_db(self):
+ """断开数据库连接"""
+ self._task = "disconnect"
+ self._task_args = None
+ self.start()
+
+ def execute_query(self, sql: str, params: Optional[tuple] = None):
+ """执行查询"""
+ self._task = "query"
+ self._task_args = (sql, params)
+ self.start()
+
+ def load_tables(self, schemas: Optional[List[str]] = None):
+ """加载表列表"""
+ self._task = "load_tables"
+ self._task_args = (schemas,)
+ self.start()
+
+ def run(self):
+ """执行任务"""
+ if self._task == "connect":
+ self._do_connect(*self._task_args)
+ elif self._task == "disconnect":
+ self._do_disconnect()
+ elif self._task == "query":
+ self._do_query(*self._task_args)
+ elif self._task == "load_tables":
+ self._do_load_tables(*self._task_args)
+
+ def _do_connect(self, dsn: str):
+ """执行连接"""
+ try:
+ import psycopg2
+ from psycopg2.extras import RealDictCursor
+
+ self.conn = psycopg2.connect(dsn, connect_timeout=10)
+ self.conn.set_session(autocommit=True)
+
+ # 测试连接
+ with self.conn.cursor() as cur:
+ cur.execute("SELECT version()")
+ version = cur.fetchone()[0]
+
+ self.connection_status.emit(True, f"已连接: {version[:50]}...")
+ except ImportError:
+ self.connection_status.emit(False, "缺少 psycopg2 模块,请安装: pip install psycopg2-binary")
+ except Exception as e:
+ self.conn = None
+ self.connection_status.emit(False, f"连接失败: {e}")
+
+ def _do_disconnect(self):
+ """执行断开连接"""
+ if self.conn:
+ try:
+ self.conn.close()
+ except Exception:
+ pass
+ self.conn = None
+ self.connection_status.emit(False, "已断开连接")
+
+ def _do_query(self, sql: str, params: Optional[tuple]):
+ """执行查询"""
+ if not self.conn:
+ self.query_error.emit("未连接到数据库")
+ return
+
+ try:
+ from psycopg2.extras import RealDictCursor
+
+ with self.conn.cursor(cursor_factory=RealDictCursor) as cur:
+ cur.execute(sql, params)
+
+ # 检查是否有结果
+ if cur.description:
+ columns = [desc[0] for desc in cur.description]
+ rows = [dict(row) for row in cur.fetchall()]
+ self.query_finished.emit(columns, rows)
+ else:
+ self.query_finished.emit([], [])
+ except Exception as e:
+ self.query_error.emit(f"查询失败: {e}")
+
+ def _do_load_tables(self, schemas: Optional[List[str]]):
+ """加载表列表"""
+ if not self.conn:
+ self.query_error.emit("未连接到数据库")
+ return
+
+ try:
+ if schemas is None:
+ schemas = ["billiards_ods", "billiards_dwd", "billiards_dws", "etl_admin"]
+
+ result = {}
+
+ for schema in schemas:
+ tables = []
+
+ # 获取表列表
+ sql = """
+ SELECT
+ t.table_name,
+ COALESCE(s.n_live_tup, 0) as row_count
+ FROM information_schema.tables t
+ LEFT JOIN pg_stat_user_tables s
+ ON t.table_name = s.relname
+ AND t.table_schema = s.schemaname
+ WHERE t.table_schema = %s
+ AND t.table_type = 'BASE TABLE'
+ ORDER BY t.table_name
+ """
+
+ with self.conn.cursor() as cur:
+ cur.execute(sql, (schema,))
+ for row in cur.fetchall():
+ table_name = row[0]
+ row_count = row[1] or 0
+
+ # 尝试获取最新更新时间
+ updated_at = None
+ try:
+ # 尝试 fetched_at 字段
+ cur.execute(f'SELECT MAX(fetched_at) FROM "{schema}"."{table_name}"')
+ result_row = cur.fetchone()
+ if result_row and result_row[0]:
+ updated_at = str(result_row[0])[:19]
+ except Exception:
+ pass
+
+ if not updated_at:
+ try:
+ # 尝试 updated_at 字段
+ cur.execute(f'SELECT MAX(updated_at) FROM "{schema}"."{table_name}"')
+ result_row = cur.fetchone()
+ if result_row and result_row[0]:
+ updated_at = str(result_row[0])[:19]
+ except Exception:
+ pass
+
+ tables.append((table_name, row_count, updated_at or "-"))
+
+ result[schema] = tables
+
+ self.tables_loaded.emit(result)
+ except Exception as e:
+ self.query_error.emit(f"加载表列表失败: {e}")
+
+ def is_connected(self) -> bool:
+ """检查是否已连接"""
+ if not self.conn:
+ return False
+ try:
+ with self.conn.cursor() as cur:
+ cur.execute("SELECT 1")
+ return True
+ except Exception:
+ return False
diff --git a/etl_billiards/gui/workers/task_worker.py b/etl_billiards/gui/workers/task_worker.py
new file mode 100644
index 0000000..1432e06
--- /dev/null
+++ b/etl_billiards/gui/workers/task_worker.py
@@ -0,0 +1,317 @@
+# -*- coding: utf-8 -*-
+"""任务执行工作线程"""
+
+import subprocess
+import sys
+import os
+from pathlib import Path
+from typing import List, Optional, Dict
+
+from PySide6.QtCore import QThread, Signal
+
+from ..utils.app_settings import app_settings
+
+
+class TaskWorker(QThread):
+ """任务执行工作线程"""
+
+ # 信号
+ output_received = Signal(str) # 收到输出行
+ task_finished = Signal(int, str) # 任务完成 (exit_code, summary)
+ error_occurred = Signal(str) # 发生错误
+ progress_updated = Signal(int, int) # 进度更新 (current, total)
+
+ def __init__(self, command: List[str], working_dir: Optional[str] = None,
+ extra_env: Optional[Dict[str, str]] = None, parent=None):
+ super().__init__(parent)
+ self.command = command
+ self.extra_env = extra_env or {}
+
+ # 工作目录优先级: 参数 > 应用设置 > 自动检测
+ if working_dir is not None:
+ self.working_dir = working_dir
+ elif app_settings.etl_project_path:
+ self.working_dir = app_settings.etl_project_path
+ else:
+ # 回退到源码目录
+ self.working_dir = str(Path(__file__).resolve().parents[2])
+
+ self.process: Optional[subprocess.Popen] = None
+ self._stop_requested = False
+ self._exit_code: Optional[int] = None
+ self._output_lines: List[str] = []
+
+ def run(self):
+ """执行任务"""
+ try:
+ self._stop_requested = False
+ self._output_lines = []
+
+ # 设置环境变量
+ env = os.environ.copy()
+ env["PYTHONIOENCODING"] = "utf-8"
+ env["PYTHONUNBUFFERED"] = "1"
+
+ # 添加项目根目录到 PYTHONPATH
+ project_root = self.working_dir
+ existing_path = env.get("PYTHONPATH", "")
+ if existing_path:
+ env["PYTHONPATH"] = f"{project_root}{os.pathsep}{existing_path}"
+ else:
+ env["PYTHONPATH"] = project_root
+
+ # 添加额外的环境变量
+ if self.extra_env:
+ for key, value in self.extra_env.items():
+ env[key] = str(value)
+ self.output_received.emit(f"[环境变量] {key}={value}")
+
+ self.output_received.emit(f"[工作目录] {self.working_dir}")
+ self.output_received.emit(f"[执行命令] {' '.join(self.command)}")
+
+ # 启动进程
+ self.process = subprocess.Popen(
+ self.command,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ text=True,
+ encoding="utf-8",
+ errors="replace",
+ cwd=self.working_dir,
+ env=env,
+ creationflags=subprocess.CREATE_NO_WINDOW if sys.platform == "win32" else 0,
+ )
+
+ # 读取输出
+ if self.process.stdout:
+ for line in iter(self.process.stdout.readline, ""):
+ if self._stop_requested:
+ break
+
+ line = line.rstrip("\n\r")
+ if line:
+ self._output_lines.append(line)
+ self.output_received.emit(line)
+
+ # 解析进度信息(如果有)
+ self._parse_progress(line)
+
+ # 等待进程结束
+ if self.process:
+ self.process.wait()
+ self._exit_code = self.process.returncode
+
+ # 生成摘要
+ summary = self._generate_summary()
+ self.task_finished.emit(self._exit_code or 0, summary)
+
+ except FileNotFoundError as e:
+ self.error_occurred.emit(f"找不到 Python 解释器: {e}")
+ self.task_finished.emit(-1, f"执行失败: {e}")
+ except Exception as e:
+ self.error_occurred.emit(f"执行出错: {e}")
+ self.task_finished.emit(-1, f"执行失败: {e}")
+ finally:
+ self.process = None
+
+ def stop(self):
+ """停止任务"""
+ self._stop_requested = True
+ if self.process:
+ try:
+ self.process.terminate()
+ # 给进程一些时间来终止
+ try:
+ self.process.wait(timeout=5)
+ except subprocess.TimeoutExpired:
+ self.process.kill()
+ except Exception:
+ pass
+
+ def _parse_progress(self, line: str):
+ """解析进度信息"""
+ # 尝试从日志中解析进度
+ # 示例: "[INFO] 处理进度: 50/100"
+ import re
+ match = re.search(r'进度[:\s]*(\d+)/(\d+)', line)
+ if match:
+ current = int(match.group(1))
+ total = int(match.group(2))
+ self.progress_updated.emit(current, total)
+
+ def _generate_summary(self) -> str:
+ """生成执行摘要"""
+ if not self._output_lines:
+ return "无输出"
+
+ return self._parse_detailed_summary()
+
+ def _parse_detailed_summary(self) -> str:
+ """解析详细的执行摘要"""
+ import re
+ import json
+
+ summary_parts = []
+
+ # 统计各类信息
+ ods_stats = [] # ODS 抓取统计
+ dwd_stats = [] # DWD 装载统计
+ integrity_stats = {} # 数据校验统计
+ errors = [] # 错误信息
+ task_results = [] # 任务结果
+
+ for line in self._output_lines:
+ # 1. 解析 ODS 抓取完成信息
+ # 格式: "xxx: 抓取完成,文件=xxx,记录数=123"
+ match = re.search(r'(\w+): 抓取完成.*记录数[=:]\s*(\d+)', line)
+ if match:
+ task_name = match.group(1)
+ record_count = int(match.group(2))
+ if record_count > 0:
+ ods_stats.append(f"{task_name}: {record_count}条")
+ continue
+
+ # 2. 解析 DWD 装载完成信息
+ # 格式: "DWD 装载完成:xxx,用时 1.02s"
+ match = re.search(r'DWD 装载完成[::]\s*(\S+).*用时\s*([\d.]+)s', line)
+ if match:
+ table_name = match.group(1).replace('billiards_dwd.', '')
+ continue
+
+ # 3. 解析任务完成统计 (JSON格式)
+ # 格式: "xxx: 完成,统计={'tables': [...]}"
+ if "完成,统计=" in line or "完成,统计=" in line:
+ try:
+ match = re.search(r"统计=(\{.+\})", line)
+ if match:
+ stats_str = match.group(1).replace("'", '"')
+ stats = json.loads(stats_str)
+
+ # 解析 DWD 装载统计
+ if 'tables' in stats:
+ total_processed = 0
+ total_inserted = 0
+ tables_with_data = []
+
+ for tbl in stats['tables']:
+ table_name = tbl.get('table', '').replace('billiards_dwd.', '')
+ processed = tbl.get('processed', 0)
+ inserted = tbl.get('inserted', 0)
+
+ if processed > 0:
+ total_processed += processed
+ tables_with_data.append(f"{table_name}({processed})")
+ elif inserted > 0:
+ total_inserted += inserted
+ tables_with_data.append(f"{table_name}(+{inserted})")
+
+ if total_processed > 0 or total_inserted > 0:
+ dwd_stats.append(f"处理维度: {total_processed}条, 新增事实: {total_inserted}条")
+ if len(tables_with_data) <= 5:
+ dwd_stats.append(f"涉及表: {', '.join(tables_with_data)}")
+ else:
+ dwd_stats.append(f"涉及 {len(tables_with_data)} 张表")
+ except Exception:
+ pass
+ continue
+
+ # 4. 解析数据校验结果
+ # 格式: "CHECK_DONE task=xxx missing=1 records=136 errors=0"
+ match = re.search(r'CHECK_DONE task=(\w+) missing=(\d+) records=(\d+)', line)
+ if match:
+ task_name = match.group(1)
+ missing = int(match.group(2))
+ records = int(match.group(3))
+ if missing > 0:
+ if 'missing_tasks' not in integrity_stats:
+ integrity_stats['missing_tasks'] = []
+ integrity_stats['missing_tasks'].append(f"{task_name}: 缺失{missing}/{records}")
+ integrity_stats['total_records'] = integrity_stats.get('total_records', 0) + records
+ integrity_stats['total_missing'] = integrity_stats.get('total_missing', 0) + missing
+ continue
+
+ # 5. 解析数据校验最终结果
+ # 格式: "结果统计: {'missing': 463, 'errors': 0, 'backfilled': 0}"
+ if "结果统计:" in line or "结果统计:" in line:
+ try:
+ match = re.search(r"\{.+\}", line)
+ if match:
+ stats_str = match.group(0).replace("'", '"')
+ stats = json.loads(stats_str)
+ integrity_stats['final_missing'] = stats.get('missing', 0)
+ integrity_stats['final_errors'] = stats.get('errors', 0)
+ integrity_stats['backfilled'] = stats.get('backfilled', 0)
+ except Exception:
+ pass
+ continue
+
+ # 6. 解析错误信息
+ if "[ERROR]" in line or "错误" in line.lower() or "error" in line.lower():
+ if "Traceback" not in line and "File " not in line:
+ errors.append(line.strip()[:100])
+
+ # 7. 解析任务完成信息
+ if "任务执行成功" in line or "ETL运行完成" in line:
+ task_results.append("✓ " + line.split("]")[-1].strip() if "]" in line else line.strip())
+ elif "任务执行失败" in line:
+ task_results.append("✗ " + line.split("]")[-1].strip() if "]" in line else line.strip())
+
+ # 构建摘要
+ if ods_stats:
+ summary_parts.append("【ODS 抓取】" + ", ".join(ods_stats[:5]))
+ if len(ods_stats) > 5:
+ summary_parts[-1] += f" 等{len(ods_stats)}项"
+
+ if dwd_stats:
+ summary_parts.append("【DWD 装载】" + "; ".join(dwd_stats))
+
+ if integrity_stats:
+ total_missing = integrity_stats.get('final_missing', integrity_stats.get('total_missing', 0))
+ total_records = integrity_stats.get('total_records', 0)
+ backfilled = integrity_stats.get('backfilled', 0)
+
+ int_summary = f"【数据校验】检查 {total_records} 条记录"
+ if total_missing > 0:
+ int_summary += f", 发现 {total_missing} 条缺失"
+ if backfilled > 0:
+ int_summary += f", 已补全 {backfilled} 条"
+ else:
+ int_summary += ", 数据完整"
+ summary_parts.append(int_summary)
+
+ # 显示缺失详情
+ if integrity_stats.get('missing_tasks'):
+ missing_detail = integrity_stats['missing_tasks'][:3]
+ summary_parts.append(" 缺失: " + "; ".join(missing_detail))
+ if len(integrity_stats['missing_tasks']) > 3:
+ summary_parts[-1] += f" 等{len(integrity_stats['missing_tasks'])}项"
+
+ if errors:
+ summary_parts.append("【错误】" + "; ".join(errors[:3]))
+
+ if task_results:
+ summary_parts.append("【结果】" + " | ".join(task_results))
+
+ if summary_parts:
+ return "\n".join(summary_parts)
+
+ # 如果没有解析到任何信息,返回最后几行关键信息
+ key_lines = []
+ for line in self._output_lines[-10:]:
+ if "完成" in line or "成功" in line or "失败" in line:
+ key_lines.append(line.strip()[:80])
+
+ if key_lines:
+ return "\n".join(key_lines[-3:])
+
+ return self._output_lines[-1] if self._output_lines else "执行完成"
+
+ @property
+ def exit_code(self) -> Optional[int]:
+ """获取退出码"""
+ return self._exit_code
+
+ @property
+ def output(self) -> str:
+ """获取完整输出"""
+ return "\n".join(self._output_lines)
diff --git a/etl_billiards/ods_row_report.json b/etl_billiards/ods_row_report.json
new file mode 100644
index 0000000..7ce930c
--- /dev/null
+++ b/etl_billiards/ods_row_report.json
@@ -0,0 +1,52 @@
+{
+ "source_counts": {
+ "assistant_accounts_master.json": 2,
+ "assistant_cancellation_records.json": 2,
+ "assistant_service_records.json": 2,
+ "goods_stock_movements.json": 2,
+ "goods_stock_summary.json": 161,
+ "group_buy_packages.json": 2,
+ "group_buy_redemption_records.json": 2,
+ "member_balance_changes.json": 2,
+ "member_profiles.json": 2,
+ "member_stored_value_cards.json": 2,
+ "payment_transactions.json": 200,
+ "platform_coupon_redemption_records.json": 200,
+ "recharge_settlements.json": 2,
+ "refund_transactions.json": 11,
+ "settlement_records.json": 2,
+ "settlement_ticket_details.json": 193,
+ "site_tables_master.json": 2,
+ "stock_goods_category_tree.json": 2,
+ "store_goods_master.json": 2,
+ "store_goods_sales_records.json": 2,
+ "table_fee_discount_records.json": 2,
+ "table_fee_transactions.json": 2,
+ "tenant_goods_master.json": 2
+ },
+ "ods_counts": {
+ "member_profiles": 199,
+ "member_balance_changes": 200,
+ "member_stored_value_cards": 200,
+ "recharge_settlements": 75,
+ "settlement_records": 200,
+ "assistant_cancellation_records": 15,
+ "assistant_accounts_master": 50,
+ "assistant_service_records": 200,
+ "site_tables_master": 71,
+ "table_fee_discount_records": 200,
+ "table_fee_transactions": 200,
+ "goods_stock_movements": 200,
+ "stock_goods_category_tree": 9,
+ "goods_stock_summary": 161,
+ "payment_transactions": 200,
+ "refund_transactions": 11,
+ "platform_coupon_redemption_records": 200,
+ "tenant_goods_master": 156,
+ "group_buy_packages": 17,
+ "group_buy_redemption_records": 200,
+ "settlement_ticket_details": 193,
+ "store_goods_master": 161,
+ "store_goods_sales_records": 200
+ }
+}
\ No newline at end of file
diff --git a/etl_billiards/orchestration/run_tracker.py b/etl_billiards/orchestration/run_tracker.py
index ca85d2f..86e745b 100644
--- a/etl_billiards/orchestration/run_tracker.py
+++ b/etl_billiards/orchestration/run_tracker.py
@@ -39,9 +39,18 @@ class RunTracker:
self.db.commit()
return run_id
- def update_run(self, run_id: int, counts: dict, status: str,
- ended_at: datetime = None, manifest: dict = None,
- error_message: str = None):
+ def update_run(
+ self,
+ run_id: int,
+ counts: dict,
+ status: str,
+ ended_at: datetime = None,
+ manifest: dict = None,
+ error_message: str = None,
+ window: dict | None = None,
+ request_params: dict | None = None,
+ overlap_seconds: int | None = None,
+ ):
"""更新运行记录"""
sql = """
UPDATE etl_admin.etl_run
@@ -54,17 +63,65 @@ class RunTracker:
status = %s,
ended_at = %s,
manifest = %s,
- error_message = %s
+ error_message = %s,
+ window_start = COALESCE(%s, window_start),
+ window_end = COALESCE(%s, window_end),
+ window_minutes = COALESCE(%s, window_minutes),
+ overlap_seconds = COALESCE(%s, overlap_seconds),
+ request_params = CASE WHEN %s IS NULL THEN request_params ELSE %s::jsonb END
WHERE run_id = %s
"""
+ def _count(v, default: int = 0) -> int:
+ if v is None:
+ return default
+ if isinstance(v, bool):
+ return int(v)
+ if isinstance(v, int):
+ return int(v)
+ if isinstance(v, str):
+ try:
+ return int(v)
+ except Exception:
+ return default
+ if isinstance(v, (list, tuple, set, dict)):
+ try:
+ return len(v)
+ except Exception:
+ return default
+ return default
+
+ safe_counts = counts or {}
+
+ window_start = None
+ window_end = None
+ window_minutes = None
+ if isinstance(window, dict):
+ window_start = window.get("start") or window.get("window_start")
+ window_end = window.get("end") or window.get("window_end")
+ window_minutes = window.get("minutes") or window.get("window_minutes")
+
+ request_json = None if request_params is None else json.dumps(request_params or {}, ensure_ascii=False)
self.db.execute(
sql,
- (counts.get("fetched", 0), counts.get("inserted", 0),
- counts.get("updated", 0), counts.get("skipped", 0),
- counts.get("errors", 0), counts.get("unknown_fields", 0),
- status, ended_at,
- json.dumps(manifest or {}, ensure_ascii=False),
- error_message, run_id)
+ (
+ _count(safe_counts.get("fetched", 0)),
+ _count(safe_counts.get("inserted", 0)),
+ _count(safe_counts.get("updated", 0)),
+ _count(safe_counts.get("skipped", 0)),
+ _count(safe_counts.get("errors", 0)),
+ _count(safe_counts.get("unknown_fields", 0)),
+ status,
+ ended_at,
+ json.dumps(manifest or {}, ensure_ascii=False),
+ error_message,
+ window_start,
+ window_end,
+ window_minutes,
+ overlap_seconds,
+ request_json,
+ request_json,
+ run_id,
+ ),
)
self.db.commit()
diff --git a/etl_billiards/orchestration/scheduler.py b/etl_billiards/orchestration/scheduler.py
index 4f6ffe0..c499a45 100644
--- a/etl_billiards/orchestration/scheduler.py
+++ b/etl_billiards/orchestration/scheduler.py
@@ -1,7 +1,17 @@
# -*- coding: utf-8 -*-
-"""ETL 调度:支持在线抓取、离线清洗入库、全流程三种模式。"""
+"""ETL 调度:支持在线抓取、离线清洗入库、全流程三种模式。
+
+说明:
+ 为了便于排障与审计,调度器默认会在每次运行时将日志写入文件:
+ `io.log_root/.log`。
+
+ - 该文件路径会同步写入 `etl_admin.etl_run.log_path` 字段(由 RunTracker 记录)。
+ - 文件日志通过给 root logger 动态挂载 FileHandler 实现,保证即便子模块使用
+ `logging.getLogger(__name__)` 也能写入同一份日志文件。
+"""
from __future__ import annotations
+import logging
import uuid
from datetime import datetime
from pathlib import Path
@@ -50,6 +60,40 @@ class ETLScheduler:
self.run_tracker = RunTracker(self.db_conn)
self.task_registry = default_registry
+ def _attach_run_file_logger(self, run_uuid: str) -> logging.Handler | None:
+ """
+ 为本次 run_uuid 动态挂载文件日志处理器。
+
+ 返回值:
+ - 成功:返回 FileHandler(调用方负责 removeHandler/close)
+ - 失败:返回 None(不中断主流程)
+ """
+ log_root = Path(self.config["io"]["log_root"])
+ try:
+ log_root.mkdir(parents=True, exist_ok=True)
+ except Exception as exc: # noqa: BLE001
+ self.logger.warning("创建日志目录失败:%s(%s)", log_root, exc)
+ return None
+
+ log_path = log_root / f"{run_uuid}.log"
+ try:
+ handler: logging.Handler = logging.FileHandler(log_path, encoding="utf-8")
+ except Exception as exc: # noqa: BLE001
+ self.logger.warning("创建文件日志失败:%s(%s)", log_path, exc)
+ return None
+
+ fmt = logging.Formatter(
+ fmt="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S",
+ )
+ handler.setFormatter(fmt)
+ handler.setLevel(logging.INFO)
+
+ # 挂到 root logger,保证各模块 logger 都能写入同一文件。
+ root_logger = logging.getLogger()
+ root_logger.addHandler(handler)
+ return handler
+
# ------------------------------------------------------------------ public
def run_tasks(self, task_codes: list | None = None):
"""按配置或传入列表执行任务。"""
@@ -59,20 +103,39 @@ class ETLScheduler:
if not task_codes:
task_codes = self.config.get("run.tasks", [])
- self.logger.info("开始运行任务: %s, run_uuid=%s", task_codes, run_uuid)
+ file_handler = self._attach_run_file_logger(run_uuid)
+ try:
+ self.logger.info("开始运行任务: %s, run_uuid=%s", task_codes, run_uuid)
- for task_code in task_codes:
- try:
- self._run_single_task(task_code, run_uuid, store_id)
- except Exception as exc: # noqa: BLE001
- self.logger.error("任务 %s 失败: %s", task_code, exc, exc_info=True)
- continue
+ for task_code in task_codes:
+ try:
+ self._run_single_task(task_code, run_uuid, store_id)
+ except Exception as exc: # noqa: BLE001
+ self.logger.error("任务 %s 失败: %s", task_code, exc, exc_info=True)
+ continue
- self.logger.info("所有任务执行完成")
+ self.logger.info("所有任务执行完成")
+ finally:
+ if file_handler is not None:
+ try:
+ logging.getLogger().removeHandler(file_handler)
+ except Exception:
+ pass
+ try:
+ file_handler.close()
+ except Exception:
+ pass
# ------------------------------------------------------------------ internals
def _run_single_task(self, task_code: str, run_uuid: str, store_id: int):
"""单个任务的抓取/清洗编排。"""
+ task_code_upper = task_code.upper()
+
+ # 工具类任务:直接执行,不记录 cursor/run
+ if task_code_upper in self.NO_DB_CONFIG_TASKS:
+ self._run_utility_task(task_code_upper, store_id)
+ return
+
task_cfg = self._load_task_config(task_code, store_id)
if not task_cfg:
self.logger.warning("任务 %s 未启用或不存在", task_code)
@@ -98,6 +161,38 @@ class ETLScheduler:
fetch_stats = None
try:
+ # ODS_* tasks (except ODS_JSON_ARCHIVE) don't implement extract/transform/load stages in this repo
+ # version, so we execute them as a single step with the appropriate API client.
+ if self._is_ods_task(task_code):
+ if self.pipeline_flow in {"FULL", "FETCH_ONLY"}:
+ result, _ = self._execute_ods_record_and_load(task_code, cursor_data, fetch_dir, run_id)
+ else:
+ source_dir = self._resolve_ingest_source(fetch_dir, None)
+ result = self._execute_ingest(task_code, cursor_data, source_dir)
+
+ self.run_tracker.update_run(
+ run_id=run_id,
+ counts=result.get("counts") or {},
+ status=self._map_run_status(result.get("status")),
+ ended_at=datetime.now(self.tz),
+ window=result.get("window"),
+ request_params=result.get("request_params"),
+ overlap_seconds=self.config.get("run.overlap_seconds"),
+ )
+
+ if (result.get("status") or "").upper() == "SUCCESS":
+ window = result.get("window")
+ if isinstance(window, dict):
+ self.cursor_mgr.advance(
+ task_id=task_id,
+ store_id=store_id,
+ window_start=window.get("start"),
+ window_end=window.get("end"),
+ run_id=run_id,
+ )
+ self._maybe_run_integrity_check(task_code, window)
+ return
+
if self._flow_includes_fetch():
fetch_stats = self._execute_fetch(task_code, cursor_data, fetch_dir, run_id)
if self.pipeline_flow == "FETCH_ONLY":
@@ -119,6 +214,9 @@ class ETLScheduler:
counts=result["counts"],
status=self._map_run_status(result["status"]),
ended_at=datetime.now(self.tz),
+ window=result.get("window"),
+ request_params=result.get("request_params"),
+ overlap_seconds=self.config.get("run.overlap_seconds"),
)
if (result.get("status") or "").upper() == "SUCCESS":
@@ -131,6 +229,7 @@ class ETLScheduler:
window_end=window.get("end"),
run_id=run_id,
)
+ self._maybe_run_integrity_check(task_code, window)
except Exception as exc: # noqa: BLE001
self.run_tracker.update_run(
@@ -158,7 +257,10 @@ class ETLScheduler:
extracted = task.extract(context)
# 抓取结束,不执行 transform/load
stats = recording_client.last_dump or {}
- fetched_count = stats.get("records") or len(extracted.get("records", [])) if isinstance(extracted, dict) else 0
+ extracted_count = 0
+ if isinstance(extracted, dict):
+ extracted_count = int(extracted.get("fetched") or 0) or len(extracted.get("records", []))
+ fetched_count = stats.get("records") or extracted_count or 0
self.logger.info(
"%s: 抓取完成,文件=%s,记录数=%s",
task_code,
@@ -167,6 +269,34 @@ class ETLScheduler:
)
return {"file": stats.get("file"), "records": fetched_count, "pages": stats.get("pages")}
+ @staticmethod
+ def _is_ods_task(task_code: str) -> bool:
+ tc = str(task_code or "").upper()
+ return tc.startswith("ODS_") and tc != "ODS_JSON_ARCHIVE"
+
+ def _execute_ods_record_and_load(
+ self,
+ task_code: str,
+ cursor_data: dict | None,
+ fetch_dir: Path,
+ run_id: int,
+ ) -> tuple[dict, dict]:
+ """
+ Execute an ODS task with RecordingAPIClient so it fetches online and writes JSON dumps.
+ (ODS tasks in this repo perform DB upsert inside execute(); there is no staged extract/load.)
+ """
+ recording_client = RecordingAPIClient(
+ base_client=self.api_client,
+ output_dir=fetch_dir,
+ task_code=task_code,
+ run_id=run_id,
+ write_pretty=self.write_pretty_json,
+ )
+ task = self.task_registry.create_task(task_code, self.config, self.db_ops, recording_client, self.logger)
+ self.logger.info("%s: ODS fetch+load start, dir=%s", task_code, fetch_dir)
+ result = task.execute(cursor_data)
+ return result, (recording_client.last_dump or {})
+
def _execute_ingest(self, task_code: str, cursor_data: dict | None, source_dir: Path):
"""本地清洗入库:使用 LocalJsonClient 回放 JSON,走原有任务 ETL。"""
local_client = LocalJsonClient(source_dir)
@@ -201,6 +331,53 @@ class ETLScheduler:
def _flow_includes_ingest(self) -> bool:
return self.pipeline_flow in {"INGEST_ONLY", "FULL"}
+ # 不需要数据库配置即可运行的任务(工具类/初始化类)
+ NO_DB_CONFIG_TASKS = {
+ # Schema 初始化任务
+ "INIT_ODS_SCHEMA",
+ "INIT_DWD_SCHEMA",
+ "INIT_DWS_SCHEMA",
+ # 质量检查任务
+ "DATA_INTEGRITY_CHECK",
+ "DWD_QUALITY_CHECK",
+ # 工具任务
+ "CHECK_CUTOFF",
+ "MANUAL_INGEST",
+ "ODS_JSON_ARCHIVE",
+ # DWS 汇总任务
+ "DWS_BUILD_ORDER_SUMMARY",
+ }
+
+ def _run_utility_task(self, task_code: str, store_id: int):
+ """
+ 执行工具类任务(不记录 cursor/run,直接执行)。
+ 这些任务不需要游标管理和运行跟踪。
+ """
+ self.logger.info("%s: 开始执行工具类任务", task_code)
+
+ try:
+ # 创建任务实例(不需要 API client,使用 None)
+ task = self.task_registry.create_task(
+ task_code, self.config, self.db_ops, None, self.logger
+ )
+
+ # 执行任务(工具类任务通常不需要 cursor_data)
+ result = task.execute(None)
+
+ status = (result.get("status") or "").upper() if isinstance(result, dict) else "SUCCESS"
+ if status == "SUCCESS":
+ self.logger.info("%s: 工具类任务执行成功", task_code)
+ if isinstance(result, dict):
+ counts = result.get("counts", {})
+ if counts:
+ self.logger.info("%s: 结果统计: %s", task_code, counts)
+ else:
+ self.logger.warning("%s: 工具类任务执行结果: %s", task_code, status)
+
+ except Exception as exc:
+ self.logger.error("%s: 工具类任务执行失败: %s", task_code, exc, exc_info=True)
+ raise
+
def _load_task_config(self, task_code: str, store_id: int) -> dict | None:
"""从数据库加载任务配置。"""
sql = """
@@ -213,6 +390,45 @@ class ETLScheduler:
rows = self.db_conn.query(sql, (store_id, task_code))
return rows[0] if rows else None
+ def _maybe_run_integrity_check(self, task_code: str, window: dict | None) -> None:
+ if not self.config.get("integrity.auto_check", False):
+ return
+ if str(task_code or "").upper() != "DWD_LOAD_FROM_ODS":
+ return
+ if not isinstance(window, dict):
+ return
+ window_start = window.get("start")
+ window_end = window.get("end")
+ if not window_start or not window_end:
+ return
+
+ try:
+ from quality.integrity_checker import IntegrityWindow, run_integrity_window
+
+ include_dimensions = bool(self.config.get("integrity.include_dimensions", False))
+ task_codes = str(self.config.get("integrity.ods_task_codes", "") or "").strip()
+ report = run_integrity_window(
+ cfg=self.config,
+ window=IntegrityWindow(
+ start=window_start,
+ end=window_end,
+ label="etl_window",
+ granularity="window",
+ ),
+ include_dimensions=include_dimensions,
+ task_codes=task_codes,
+ logger=self.logger,
+ write_report=True,
+ )
+ self.logger.info(
+ "Integrity check done: report=%s missing=%s errors=%s",
+ report.get("report_path"),
+ report.get("api_to_ods", {}).get("total_missing"),
+ report.get("api_to_ods", {}).get("total_errors"),
+ )
+ except Exception as exc: # noqa: BLE001
+ self.logger.warning("Integrity check failed: %s", exc, exc_info=True)
+
def close(self):
"""关闭连接。"""
self.db_conn.close()
diff --git a/etl_billiards/orchestration/task_registry.py b/etl_billiards/orchestration/task_registry.py
index 5668174..c30c3cc 100644
--- a/etl_billiards/orchestration/task_registry.py
+++ b/etl_billiards/orchestration/task_registry.py
@@ -15,10 +15,19 @@ from tasks.table_discount_task import TableDiscountTask
from tasks.assistant_abolish_task import AssistantAbolishTask
from tasks.ledger_task import LedgerTask
from tasks.ods_tasks import ODS_TASK_CLASSES
-from tasks.ticket_dwd_task import TicketDwdTask
from tasks.manual_ingest_task import ManualIngestTask
from tasks.payments_dwd_task import PaymentsDwdTask
from tasks.members_dwd_task import MembersDwdTask
+from tasks.init_schema_task import InitOdsSchemaTask
+from tasks.init_dwd_schema_task import InitDwdSchemaTask
+from tasks.dwd_load_task import DwdLoadTask
+from tasks.ticket_dwd_task import TicketDwdTask
+from tasks.dwd_quality_task import DwdQualityTask
+from tasks.ods_json_archive_task import OdsJsonArchiveTask
+from tasks.check_cutoff_task import CheckCutoffTask
+from tasks.init_dws_schema_task import InitDwsSchemaTask
+from tasks.dws_build_order_summary_task import DwsBuildOrderSummaryTask
+from tasks.data_integrity_task import DataIntegrityTask
class TaskRegistry:
"""任务注册和工厂"""
@@ -64,5 +73,14 @@ default_registry.register("TICKET_DWD", TicketDwdTask)
default_registry.register("MANUAL_INGEST", ManualIngestTask)
default_registry.register("PAYMENTS_DWD", PaymentsDwdTask)
default_registry.register("MEMBERS_DWD", MembersDwdTask)
+default_registry.register("INIT_ODS_SCHEMA", InitOdsSchemaTask)
+default_registry.register("INIT_DWD_SCHEMA", InitDwdSchemaTask)
+default_registry.register("DWD_LOAD_FROM_ODS", DwdLoadTask)
+default_registry.register("DWD_QUALITY_CHECK", DwdQualityTask)
+default_registry.register("ODS_JSON_ARCHIVE", OdsJsonArchiveTask)
+default_registry.register("CHECK_CUTOFF", CheckCutoffTask)
+default_registry.register("DATA_INTEGRITY_CHECK", DataIntegrityTask)
+default_registry.register("INIT_DWS_SCHEMA", InitDwsSchemaTask)
+default_registry.register("DWS_BUILD_ORDER_SUMMARY", DwsBuildOrderSummaryTask)
for code, task_cls in ODS_TASK_CLASSES.items():
default_registry.register(code, task_cls)
diff --git a/etl_billiards/pytest.ini b/etl_billiards/pytest.ini
new file mode 100644
index 0000000..a635c5c
--- /dev/null
+++ b/etl_billiards/pytest.ini
@@ -0,0 +1,2 @@
+[pytest]
+pythonpath = .
diff --git a/etl_billiards/quality/integrity_checker.py b/etl_billiards/quality/integrity_checker.py
new file mode 100644
index 0000000..bd859bf
--- /dev/null
+++ b/etl_billiards/quality/integrity_checker.py
@@ -0,0 +1,390 @@
+# -*- coding: utf-8 -*-
+"""Integrity checks across API -> ODS -> DWD."""
+from __future__ import annotations
+
+from dataclasses import dataclass
+from datetime import date, datetime, time, timedelta
+from pathlib import Path
+from typing import Any, Dict, Iterable, List, Tuple
+from zoneinfo import ZoneInfo
+
+import json
+
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+from tasks.dwd_load_task import DwdLoadTask
+from scripts.check_ods_gaps import run_gap_check
+
+AMOUNT_KEYWORDS = ("amount", "money", "fee", "balance")
+
+
+@dataclass(frozen=True)
+class IntegrityWindow:
+ start: datetime
+ end: datetime
+ label: str
+ granularity: str
+
+
+def _ensure_tz(dt: datetime, tz: ZoneInfo) -> datetime:
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=tz)
+ return dt.astimezone(tz)
+
+
+def _month_start(day: date) -> date:
+ return date(day.year, day.month, 1)
+
+
+def _next_month(day: date) -> date:
+ if day.month == 12:
+ return date(day.year + 1, 1, 1)
+ return date(day.year, day.month + 1, 1)
+
+
+def _date_to_start(dt: date, tz: ZoneInfo) -> datetime:
+ return datetime.combine(dt, time.min).replace(tzinfo=tz)
+
+
+def _date_to_end_exclusive(dt: date, tz: ZoneInfo) -> datetime:
+ return datetime.combine(dt, time.min).replace(tzinfo=tz) + timedelta(days=1)
+
+
+def build_history_windows(start_dt: datetime, end_dt: datetime, tz: ZoneInfo) -> List[IntegrityWindow]:
+ """Build weekly windows for current month, monthly windows for earlier months."""
+ start_dt = _ensure_tz(start_dt, tz)
+ end_dt = _ensure_tz(end_dt, tz)
+ if end_dt <= start_dt:
+ return []
+
+ start_date = start_dt.date()
+ end_date = end_dt.date()
+ current_month_start = _month_start(end_date)
+
+ windows: List[IntegrityWindow] = []
+ cur = start_date
+ while cur <= end_date:
+ month_start = _month_start(cur)
+ month_end_exclusive = _next_month(cur)
+ range_start = max(cur, month_start)
+ range_end = min(end_date, month_end_exclusive - timedelta(days=1))
+
+ if month_start == current_month_start:
+ week_start = range_start
+ while week_start <= range_end:
+ week_end = min(week_start + timedelta(days=6), range_end)
+ w_start_dt = _date_to_start(week_start, tz)
+ w_end_dt = _date_to_end_exclusive(week_end, tz)
+ if w_start_dt < end_dt and w_end_dt > start_dt:
+ windows.append(
+ IntegrityWindow(
+ start=max(w_start_dt, start_dt),
+ end=min(w_end_dt, end_dt),
+ label=f"week_{week_start.isoformat()}",
+ granularity="week",
+ )
+ )
+ week_start = week_end + timedelta(days=1)
+ else:
+ m_start_dt = _date_to_start(range_start, tz)
+ m_end_dt = _date_to_end_exclusive(range_end, tz)
+ if m_start_dt < end_dt and m_end_dt > start_dt:
+ windows.append(
+ IntegrityWindow(
+ start=max(m_start_dt, start_dt),
+ end=min(m_end_dt, end_dt),
+ label=f"month_{month_start.isoformat()}",
+ granularity="month",
+ )
+ )
+ cur = month_end_exclusive
+
+ return windows
+
+
+def _split_table(name: str, default_schema: str) -> Tuple[str, str]:
+ if "." in name:
+ schema, table = name.split(".", 1)
+ return schema, table
+ return default_schema, name
+
+
+def _pick_time_column(dwd_cols: Iterable[str], ods_cols: Iterable[str]) -> str | None:
+ lower_cols = {c.lower() for c in dwd_cols} & {c.lower() for c in ods_cols}
+ for candidate in DwdLoadTask.FACT_ORDER_CANDIDATES:
+ if candidate.lower() in lower_cols:
+ return candidate.lower()
+ return None
+
+
+def _fetch_columns(cur, schema: str, table: str) -> Tuple[List[str], Dict[str, str]]:
+ cur.execute(
+ """
+ SELECT column_name, data_type
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """,
+ (schema, table),
+ )
+ cols = []
+ types: Dict[str, str] = {}
+ for name, data_type in cur.fetchall():
+ cols.append(name)
+ types[name.lower()] = (data_type or "").lower()
+ return cols, types
+
+
+def _amount_columns(cols: List[str], types: Dict[str, str]) -> List[str]:
+ numeric_types = {"numeric", "double precision", "integer", "bigint", "smallint", "real", "decimal"}
+ out = []
+ for col in cols:
+ lc = col.lower()
+ if types.get(lc) not in numeric_types:
+ continue
+ if any(key in lc for key in AMOUNT_KEYWORDS):
+ out.append(lc)
+ return out
+
+
+def _count_table(cur, schema: str, table: str, time_col: str | None, window: IntegrityWindow | None) -> int:
+ where = ""
+ params: List[Any] = []
+ if time_col and window:
+ where = f'WHERE "{time_col}" >= %s AND "{time_col}" < %s'
+ params = [window.start, window.end]
+ sql = f'SELECT COUNT(1) FROM "{schema}"."{table}" {where}'
+ cur.execute(sql, params)
+ row = cur.fetchone()
+ return int(row[0] if row else 0)
+
+
+def _sum_column(cur, schema: str, table: str, col: str, time_col: str | None, window: IntegrityWindow | None) -> float:
+ where = ""
+ params: List[Any] = []
+ if time_col and window:
+ where = f'WHERE "{time_col}" >= %s AND "{time_col}" < %s'
+ params = [window.start, window.end]
+ sql = f'SELECT COALESCE(SUM("{col}"), 0) FROM "{schema}"."{table}" {where}'
+ cur.execute(sql, params)
+ row = cur.fetchone()
+ return float(row[0] if row else 0)
+
+
+def run_dwd_vs_ods_check(
+ *,
+ cfg: AppConfig,
+ window: IntegrityWindow | None,
+ include_dimensions: bool,
+) -> Dict[str, Any]:
+ dsn = cfg["db"]["dsn"]
+ session = cfg["db"].get("session")
+ db_conn = DatabaseConnection(dsn=dsn, session=session)
+ try:
+ with db_conn.conn.cursor() as cur:
+ results: List[Dict[str, Any]] = []
+ table_map = DwdLoadTask.TABLE_MAP
+ for dwd_table, ods_table in table_map.items():
+ if not include_dimensions and ".dim_" in dwd_table:
+ continue
+ schema_dwd, name_dwd = _split_table(dwd_table, "billiards_dwd")
+ schema_ods, name_ods = _split_table(ods_table, "billiards_ods")
+ try:
+ dwd_cols, dwd_types = _fetch_columns(cur, schema_dwd, name_dwd)
+ ods_cols, ods_types = _fetch_columns(cur, schema_ods, name_ods)
+ time_col = _pick_time_column(dwd_cols, ods_cols)
+ count_dwd = _count_table(cur, schema_dwd, name_dwd, time_col, window)
+ count_ods = _count_table(cur, schema_ods, name_ods, time_col, window)
+
+ dwd_amount_cols = _amount_columns(dwd_cols, dwd_types)
+ ods_amount_cols = _amount_columns(ods_cols, ods_types)
+ common_amount_cols = sorted(set(dwd_amount_cols) & set(ods_amount_cols))
+ amounts: List[Dict[str, Any]] = []
+ for col in common_amount_cols:
+ dwd_sum = _sum_column(cur, schema_dwd, name_dwd, col, time_col, window)
+ ods_sum = _sum_column(cur, schema_ods, name_ods, col, time_col, window)
+ amounts.append(
+ {
+ "column": col,
+ "dwd_sum": dwd_sum,
+ "ods_sum": ods_sum,
+ "diff": dwd_sum - ods_sum,
+ }
+ )
+
+ results.append(
+ {
+ "dwd_table": dwd_table,
+ "ods_table": ods_table,
+ "windowed": bool(time_col and window),
+ "window_col": time_col,
+ "count": {"dwd": count_dwd, "ods": count_ods, "diff": count_dwd - count_ods},
+ "amounts": amounts,
+ }
+ )
+ except Exception as exc: # noqa: BLE001
+ results.append(
+ {
+ "dwd_table": dwd_table,
+ "ods_table": ods_table,
+ "windowed": bool(window),
+ "window_col": None,
+ "count": {"dwd": None, "ods": None, "diff": None},
+ "amounts": [],
+ "error": f"{type(exc).__name__}: {exc}",
+ }
+ )
+
+ total_count_diff = sum(
+ int(item.get("count", {}).get("diff") or 0)
+ for item in results
+ if isinstance(item.get("count", {}).get("diff"), (int, float))
+ )
+ return {
+ "tables": results,
+ "total_count_diff": total_count_diff,
+ }
+ finally:
+ db_conn.close()
+
+
+def _default_report_path(prefix: str) -> Path:
+ root = Path(__file__).resolve().parents[1]
+ stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+ return root / "reports" / f"{prefix}_{stamp}.json"
+
+
+def run_integrity_window(
+ *,
+ cfg: AppConfig,
+ window: IntegrityWindow,
+ include_dimensions: bool,
+ task_codes: str,
+ logger,
+ write_report: bool,
+ report_path: Path | None = None,
+ window_split_unit: str | None = None,
+ window_compensation_hours: int | None = None,
+) -> Dict[str, Any]:
+ total_seconds = max(0, int((window.end - window.start).total_seconds()))
+ if total_seconds >= 86400:
+ window_days = max(1, total_seconds // 86400)
+ window_hours = 0
+ else:
+ window_days = 0
+ window_hours = max(1, total_seconds // 3600 or 1)
+
+ ods_payload = run_gap_check(
+ cfg=cfg,
+ start=window.start,
+ end=window.end,
+ window_days=window_days,
+ window_hours=window_hours,
+ page_size=int(cfg.get("api.page_size") or 200),
+ chunk_size=500,
+ sample_limit=50,
+ sleep_per_window=0,
+ sleep_per_page=0,
+ task_codes=task_codes,
+ from_cutoff=False,
+ cutoff_overlap_hours=24,
+ allow_small_window=True,
+ logger=logger,
+ window_split_unit=window_split_unit,
+ window_compensation_hours=window_compensation_hours,
+ )
+
+ dwd_payload = run_dwd_vs_ods_check(
+ cfg=cfg,
+ window=window,
+ include_dimensions=include_dimensions,
+ )
+
+ report = {
+ "mode": "window",
+ "window": {
+ "start": window.start.isoformat(),
+ "end": window.end.isoformat(),
+ "label": window.label,
+ "granularity": window.granularity,
+ },
+ "api_to_ods": ods_payload,
+ "ods_to_dwd": dwd_payload,
+ "generated_at": datetime.now(ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))).isoformat(),
+ }
+
+ if write_report:
+ path = report_path or _default_report_path("data_integrity_window")
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
+ report["report_path"] = str(path)
+
+ return report
+
+
+def run_integrity_history(
+ *,
+ cfg: AppConfig,
+ start_dt: datetime,
+ end_dt: datetime,
+ include_dimensions: bool,
+ task_codes: str,
+ logger,
+ write_report: bool,
+ report_path: Path | None = None,
+) -> Dict[str, Any]:
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ windows = build_history_windows(start_dt, end_dt, tz)
+ results: List[Dict[str, Any]] = []
+ total_missing = 0
+ total_errors = 0
+
+ for window in windows:
+ logger.info("校验窗口 起始=%s 结束=%s", window.start, window.end)
+ payload = run_integrity_window(
+ cfg=cfg,
+ window=window,
+ include_dimensions=include_dimensions,
+ task_codes=task_codes,
+ logger=logger,
+ write_report=False,
+ )
+ results.append(payload)
+ total_missing += int(payload.get("api_to_ods", {}).get("total_missing") or 0)
+ total_errors += int(payload.get("api_to_ods", {}).get("total_errors") or 0)
+
+ report = {
+ "mode": "history",
+ "start": _ensure_tz(start_dt, tz).isoformat(),
+ "end": _ensure_tz(end_dt, tz).isoformat(),
+ "windows": results,
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ "generated_at": datetime.now(tz).isoformat(),
+ }
+
+ if write_report:
+ path = report_path or _default_report_path("data_integrity_history")
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
+ report["report_path"] = str(path)
+
+ return report
+
+
+def compute_last_etl_end(cfg: AppConfig) -> datetime | None:
+ dsn = cfg["db"]["dsn"]
+ session = cfg["db"].get("session")
+ db_conn = DatabaseConnection(dsn=dsn, session=session)
+ try:
+ rows = db_conn.query(
+ "SELECT MAX(window_end) AS mx FROM etl_admin.etl_run WHERE store_id = %s",
+ (cfg.get("app.store_id"),),
+ )
+ mx = rows[0]["mx"] if rows else None
+ if isinstance(mx, datetime):
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ return _ensure_tz(mx, tz)
+ finally:
+ db_conn.close()
+ return None
diff --git a/etl_billiards/reports/__init__.py b/etl_billiards/reports/__init__.py
new file mode 100644
index 0000000..2d9f13d
--- /dev/null
+++ b/etl_billiards/reports/__init__.py
@@ -0,0 +1,3 @@
+# -*- coding: utf-8 -*-
+"""Reports package."""
+
diff --git a/etl_billiards/reports/assistant_extra_lessons_13811638071_2025-11-14.csv b/etl_billiards/reports/assistant_extra_lessons_13811638071_2025-11-14.csv
new file mode 100644
index 0000000..73bcbb0
--- /dev/null
+++ b/etl_billiards/reports/assistant_extra_lessons_13811638071_2025-11-14.csv
@@ -0,0 +1,7 @@
+会员名称,会员手机号,订单号,开始时间,助教课时,结账时间
+葛先生,13811638071,2987682979566149,2025-12-01 00:08:19,小燕(2h0m),2025-12-01 00:08:25
+葛先生,13811638071,2996398357319941,2025-12-07 03:54:04,小燕(6h0m),2025-12-07 03:54:45
+葛先生,13811638071,3003030187398085,2025-12-11 20:20:19,小燕(4h0m),2025-12-11 20:20:22
+葛先生,13811638071,3008791223945669,2025-12-15 22:00:44,小燕(2h0m),2025-12-15 22:00:48
+葛先生,13811638071,3010440130430917,2025-12-17 01:58:06,小燕(2h0m),2025-12-17 01:58:11
+葛先生,13811638071,3025720252254149,2025-12-27 21:01:50,小燕(4h0m),2025-12-27 21:01:53
diff --git a/etl_billiards/reports/assistant_orders_13811638071_2025-09-01.csv b/etl_billiards/reports/assistant_orders_13811638071_2025-09-01.csv
new file mode 100644
index 0000000..39e4855
--- /dev/null
+++ b/etl_billiards/reports/assistant_orders_13811638071_2025-09-01.csv
@@ -0,0 +1,153 @@
+会员名称,会员手机号,订单号,桌台(房间)名称,开始时间,持续时间,助教挂钟信息,结账时间
+葛先生,13811638071,2957496003612357,B8,2025-11-09 16:20:32,2h 0m,周周(1h57m),2025-11-09 18:27:12
+葛先生,13811638071,2982280563167941,A2,2025-11-27 04:32:42,4h 53m,阿清(4h49m) 小燕(4h53m),2025-11-27 11:33:19
+葛先生,13811638071,2984703823612613,VIP5,2025-11-28 21:37:46,10h 8m,小燕(8h39m) 阿清(10h7m),2025-11-29 07:46:38
+葛先生,13811638071,2986305074877125,VIP5,2025-11-30 00:46:38,6h 16m,小燕(6h15m),2025-11-30 07:06:16
+葛先生,13811638071,2987452433699397,S1,2025-11-30 20:13:48,2h 15m,小燕(1h59m) 乔西(2h15m),2025-11-30 22:29:58
+葛先生,13811638071,2990547445273157,TV,2025-12-03 00:42:12,8h 10m,小燕(8h10m),2025-12-03 08:52:52
+葛先生,13811638071,2991901466284741,A3,2025-12-03 23:39:35,7h 16m,小燕(7h16m),2025-12-04 09:59:55
+葛先生,13811638071,2993396100174533,A3,2025-12-05 01:00:00,0h 25m,,2025-12-05 09:16:58
+葛先生,13811638071,2993421047679685,TV,2025-12-05 01:25:23,7h 50m,小燕(8h16m),2025-12-05 09:16:58
+葛先生,13811638071,2994596202270981,B3,2025-12-05 21:20:49,0h 35m,,2025-12-06 03:19:33
+葛先生,13811638071,2994624795250949,TV,2025-12-05 21:49:54,5h 29m,小燕(5h29m),2025-12-06 03:19:33
+葛先生,13811638071,3002915771880325,TV,2025-12-11 18:23:55,1h 6m,球球(1h6m),2025-12-12 05:16:57
+葛先生,13811638071,3003029803307781,A6,2025-12-11 20:19:55,2h 50m,小燕(2h50m),2025-12-12 01:50:19
+葛先生,13811638071,3003192948659141,888,2025-12-11 23:05:52,6h 0m,涛涛(5h51m) 小燕(5h56m) 梦梦(2h52m) 年糕(2h38m),2025-12-12 05:16:57
+葛先生,13811638071,3003354125276101,A1,2025-12-12 01:49:50,0h 0m,,2025-12-12 01:50:19
+葛先生,13811638071,3003355747341189,补时长4,2025-12-12 01:51:29,0h 1m,,2025-12-12 01:51:48
+葛先生,13811638071,3004579787884613,TV,2025-12-12 22:36:38,8h 10m,小燕(8h10m),2025-12-13 06:47:52
+葛先生,13811638071,3005655255435397,A11,2025-12-13 16:50:40,4h 53m,小燕(4h53m),2025-12-13 21:44:28
+葛先生,13811638071,3005944536778822,补时长7,2025-12-13 21:44:56,2h 0m,,2025-12-13 21:45:20
+葛先生,13811638071,3006295607298309,A1,2025-12-14 03:42:04,0h 43m,小燕(0h43m),2025-12-14 04:26:40
+葛先生,13811638071,3007126951397381,A1,2025-12-14 17:47:45,2h 5m,小燕(2h5m),2025-12-14 19:53:51
+葛先生,13811638071,3007250978523205,补时长5,2025-12-14 19:53:55,0h 1m,,2025-12-14 19:54:17
+葛先生,13811638071,3007446854797445,TV,2025-12-14 23:13:10,5h 57m,阿清(4h5m) 阿清(1h5m) 小燕(5h57m),2025-12-15 05:11:18
+葛先生,13811638071,3008791817832389,A1,2025-12-15 22:01:20,2h 19m,小燕(2h19m),2025-12-16 02:42:42
+葛先生,13811638071,3008834924841285,S1,2025-12-15 22:45:11,3h 55m,苏苏(2h28m),2025-12-16 02:42:42
+葛先生,13811638071,3009076506036165,A2,2025-12-16 02:50:56,3h 40m,小燕(3h39m),2025-12-16 06:32:44
+葛先生,13811638071,3009492999244293,补时长7,2025-12-16 09:54:37,3h 0m,,2025-12-16 09:54:56
+葛先生,13811638071,3010218131671557,A1,2025-12-16 22:12:16,3h 18m,小燕(3h18m) 阿清(2h43m),2025-12-17 01:31:11
+葛先生,13811638071,3011469546309317,A1,2025-12-17 19:25:16,1h 34m,小燕(1h34m),2025-12-17 22:04:09
+葛先生,13811638071,3011552955975237,C2,2025-12-17 20:50:07,1h 13m,小燕(1h3m),2025-12-17 22:04:09
+葛先生,13811638071,3011630421837381,A18,2025-12-17 22:08:55,3h 3m,小燕(3h3m),2025-12-18 01:12:30
+葛先生,13811638071,3012931996487173,TV,2025-12-18 20:12:57,5h 38m,小燕(5h38m),2025-12-19 01:53:16
+葛先生,13811638071,3013266727145349,补时长5,2025-12-19 01:53:27,2h 0m,,2025-12-19 01:53:55
+葛先生,13811638071,3013302603681669,A6,2025-12-19 02:29:57,0h 30m,小燕(0h29m),2025-12-19 03:00:10
+葛先生,13811638071,3013331369283205,A1,2025-12-19 02:59:12,0h 18m,,2025-12-19 02:59:41
+葛先生,13811638071,3014164982173317,A6,2025-12-19 17:07:12,11h 18m,小燕(11h18m) 阿清(2h0m),2025-12-20 06:59:01
+葛先生,13811638071,3014479760183173,TV,2025-12-19 22:27:25,8h 31m,阿清(8h22m) 小燕(2h53m),2025-12-20 06:59:01
+葛先生,13811638071,3015171680994757,补时长7,2025-12-20 10:11:16,3h 0m,,2025-12-20 10:11:36
+葛先生,13811638071,3015847664387653,S2,2025-12-20 21:38:55,0h 56m,球球(0h56m),2025-12-20 22:38:26
+葛先生,13811638071,3015856577545861,S1,2025-12-20 21:47:59,1h 12m,小燕(1h12m),2025-12-20 23:01:49
+葛先生,13811638071,3015974337283525,补时长6,2025-12-20 23:47:46,3h 0m,,2025-12-20 23:48:13
+葛先生,13811638071,3015974988367429,C4,2025-12-20 23:48:26,4h 28m,小燕(4h28m),2025-12-21 04:17:32
+葛先生,13811638071,3016300766643845,TV,2025-12-21 05:19:50,0h 56m,小燕(0h56m),2025-12-21 06:16:53
+葛先生,13811638071,3016653147375173,补时长7,2025-12-21 11:18:18,2h 0m,,2025-12-21 11:18:40
+葛先生,13811638071,3017225201927749,S1,2025-12-21 21:00:13,1h 28m,,2025-12-21 22:30:16
+葛先生,13811638071,3017273506465285,C5,2025-12-21 21:49:21,1h 24m,千千(1h12m),2025-12-21 23:45:38
+葛先生,13811638071,3017388287231429,补时长6,2025-12-21 23:46:07,0h 0m,,2025-12-21 23:46:27
+葛先生,13811638071,3017486080099845,A1,2025-12-22 01:25:36,1h 49m,小燕(1h49m),2025-12-22 03:15:17
+葛先生,13811638071,3017593957697157,补时长6,2025-12-22 03:15:20,0h 0m,,2025-12-22 03:15:37
+葛先生,13811638071,3017596515419717,A1,2025-12-22 03:17:56,3h 49m,小燕(3h49m),2025-12-22 07:08:11
+葛先生,13811638071,3018642766775813,S1,2025-12-22 21:02:14,1h 7m,小燕(1h7m),2025-12-22 22:10:33
+葛先生,13811638071,3018644316587589,补时长7,2025-12-22 21:03:49,0h 0m,,2025-12-22 21:04:09
+葛先生,13811638071,3018709942093445,S1,2025-12-22 22:10:34,0h 43m,小燕(0h43m),2025-12-22 22:54:21
+葛先生,13811638071,3018710150219205,补时长6,2025-12-22 22:10:47,0h 0m,,2025-12-22 22:11:08
+葛先生,13811638071,3018753009468933,S1,2025-12-22 22:54:23,1h 3m,小燕(1h3m),2025-12-22 23:58:44
+葛先生,13811638071,3018766856488389,补时长6,2025-12-22 23:08:28,0h 0m,,2025-12-22 23:08:51
+葛先生,13811638071,3018816489850309,补时长7,2025-12-22 23:58:58,0h 0m,,2025-12-22 23:59:34
+葛先生,13811638071,3018826595370437,M7,2025-12-23 00:09:14,4h 0m,小燕(3h59m),2025-12-23 04:23:37
+葛先生,13811638071,3019076971070917,补时长6,2025-12-23 04:23:56,2h 0m,,2025-12-23 04:24:21
+葛先生,13811638071,3019077416650181,A1,2025-12-23 04:24:23,3h 7m,小燕(3h7m),2025-12-23 07:32:22
+葛先生,13811638071,3019262758979077,补时长6,2025-12-23 07:32:56,0h 0m,,2025-12-23 07:34:10
+葛先生,13811638071,3020101562009093,A6,2025-12-23 21:46:12,10h 2m,小燕(10h1m),2025-12-24 07:48:47
+葛先生,13811638071,3020694538569157,补时长5,2025-12-24 07:49:25,3h 0m,,2025-12-24 07:49:46
+葛先生,13811638071,3021420856576006,S1,2025-12-24 20:08:16,1h 22m,小燕(1h22m),2025-12-24 21:30:46
+葛先生,13811638071,3021501988194373,S1,2025-12-24 21:30:47,1h 50m,小燕(1h49m),2025-12-24 23:21:38
+葛先生,13811638071,3021610987734853,S1,2025-12-24 23:21:40,2h 21m,小燕(2h21m),2025-12-25 01:43:51
+葛先生,13811638071,3021770635823109,A6,2025-12-25 02:04:04,7h 56m,小燕(7h56m),2025-12-25 12:08:55
+葛先生,13811638071,3022365496854533,补时长6,2025-12-25 12:09:12,4h 0m,,2025-12-25 12:09:46
+葛先生,13811638071,3022873228429253,S1,2025-12-25 20:45:41,1h 55m,小燕(1h55m),2025-12-25 22:42:03
+葛先生,13811638071,3022987729340421,S1,2025-12-25 22:42:10,1h 9m,小燕(1h9m),2025-12-25 23:52:24
+葛先生,13811638071,3023056813000773,S1,2025-12-25 23:52:26,0h 58m,小燕(0h58m),2025-12-26 00:51:10
+葛先生,13811638071,3023057336322053,补时长5,2025-12-25 23:52:58,0h 0m,,2025-12-25 23:53:18
+葛先生,13811638071,3023118312458181,A6,2025-12-26 00:55:00,5h 59m,小燕(5h59m),2025-12-26 06:55:32
+葛先生,13811638071,3024330328901573,C1,2025-12-26 21:27:56,3h 14m,小燕(3h14m),2025-12-27 00:42:31
+葛先生,13811638071,3024521672149061,A6,2025-12-27 00:42:34,4h 56m,小燕(4h56m),2025-12-27 05:43:00
+葛先生,13811638071,3024522484762565,补时长6,2025-12-27 00:43:24,2h 0m,,2025-12-27 00:43:51
+葛先生,13811638071,3025075373508677,补时长7,2025-12-27 10:05:50,2h 0m,,2025-12-27 10:06:18
+葛先生,13811638071,3025697485457477,A12,2025-12-27 20:38:40,0h 24m,小燕(0h24m),2025-12-27 21:03:38
+葛先生,13811638071,3025926993020741,A18,2025-12-28 00:32:08,3h 59m,小燕(3h58m),2025-12-28 04:31:30
+葛先生,13811638071,3026162441734149,补时长5,2025-12-28 04:31:39,1h 40m,,2025-12-28 04:32:29
+葛先生,13811638071,3027018732144709,A8,2025-12-28 19:02:43,1h 5m,小燕(1h5m),2025-12-28 20:08:25
+葛先生,13811638071,3027082894100549,S1,2025-12-28 20:07:59,0h 47m,小燕(0h47m),2025-12-28 20:55:54
+葛先生,13811638071,3027086248364101,A8,2025-12-28 20:11:24,0h 32m,,2025-12-28 20:11:45
+葛先生,13811638071,3027130023888837,S1,2025-12-28 20:55:56,0h 42m,,2025-12-28 22:48:42
+葛先生,13811638071,3027130329974789,A6,2025-12-28 20:56:14,0h 32m,,2025-12-28 20:56:31
+葛先生,13811638071,3027171803039749,VIP5,2025-12-28 21:38:25,1h 9m,小燕(1h52m),2025-12-28 22:48:42
+葛先生,13811638071,3027240911620101,VIP5,2025-12-28 22:48:44,0h 42m,小燕(0h42m),2025-12-28 23:32:00
+葛先生,13811638071,3027274797680709,A1,2025-12-28 23:23:12,0h 4m,,2025-12-29 00:45:50
+葛先生,13811638071,3027279097726917,C2,2025-12-28 23:27:34,1h 17m,婉婉(1h17m),2025-12-29 00:45:50
+葛先生,13811638071,3027283487705029,VIP5,2025-12-28 23:32:02,1h 38m,小燕(1h38m),2025-12-29 01:10:27
+葛先生,13811638071,3027381047756741,补时长7,2025-12-29 01:11:17,0h 0m,,2025-12-29 01:11:47
+葛先生,13811638071,3027494215747397,A1,2025-12-29 03:06:24,0h 0m,小燕(1h50m),2025-12-29 03:06:51
+葛先生,13811638071,3027520016877573,补时长5,2025-12-29 03:32:39,1h 40m,,2025-12-29 03:33:33
+葛先生,13811638071,3028365240272837,A6,2025-12-29 17:52:27,2h 3m,小燕(2h3m),2025-12-29 19:58:42
+葛先生,13811638071,3028488531724357,M5,2025-12-29 19:57:52,3h 3m,小燕(3h3m),2025-12-29 23:04:58
+葛先生,13811638071,3028489795159877,A6,2025-12-29 19:59:09,1h 2m,,2025-12-29 19:59:31
+葛先生,13811638071,3028620706809861,VIP5,2025-12-29 22:12:19,1h 2m,小柔(1h2m) 小燕(0h6m),2025-12-29 23:16:04
+葛先生,13811638071,3028672505759557,补时长7,2025-12-29 23:05:01,0h 0m,,2025-12-29 23:05:28
+葛先生,13811638071,3028796631942981,A1,2025-12-30 01:11:17,0h 0m,小燕(1h12m),2025-12-30 01:12:20
+葛先生,13811638071,3028797785933637,补时长6,2025-12-30 01:12:28,0h 0m,,2025-12-30 01:12:43
+葛先生,13811638071,3028798611277893,A6,2025-12-30 01:13:18,0h 51m,小燕(0h50m),2025-12-30 02:04:34
+葛先生,13811638071,3029823520163653,A6,2025-12-30 18:35:53,1h 30m,小燕(1h30m),2025-12-30 20:06:17
+葛先生,13811638071,3029912671930309,A2,2025-12-30 20:06:35,0h 45m,,2025-12-30 20:07:12
+葛先生,13811638071,3029920336283461,S1,2025-12-30 20:14:23,1h 9m,小燕(1h8m),2025-12-30 21:26:01
+葛先生,13811638071,3029953608239109,S3,2025-12-30 20:48:13,0h 54m,,2025-12-30 21:43:22
+葛先生,13811638071,3029990793086789,S1,2025-12-30 21:26:03,1h 22m,小燕(1h1m) 阿清(0h20m),2025-12-30 22:48:21
+葛先生,13811638071,3029991615416389,A6,2025-12-30 21:26:53,0h 50m,,2025-12-30 21:27:30
+葛先生,13811638071,3030051846162437,A6,2025-12-30 22:28:09,1h 35m,小燕(1h13m),2025-12-31 00:03:58
+葛先生,13811638071,3030071938451269,S1,2025-12-30 22:48:36,0h 45m,阿清(0h45m),2025-12-30 23:34:52
+葛先生,13811638071,3030329100781637,补时长2,2025-12-31 03:10:12,0h 1m,,2025-12-31 03:10:58
+葛先生,13811638071,3031047867485317,VIP1,2025-12-31 15:21:22,2h 15m,小燕(2h15m),2025-12-31 18:30:37
+葛先生,13811638071,3031246571603653,补时长2,2025-12-31 18:43:30,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3031246638532229,补时长3,2025-12-31 18:43:34,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3036870032656645,A6,2026-01-04 18:03:58,2h 15m,小燕(2h15m),2026-01-04 20:20:13
+葛先生,13811638071,3037004116691653,补时长7,2026-01-04 20:20:22,0h 0m,,2026-01-04 20:20:58
+葛先生,13811638071,3037130243574469,A7,2026-01-04 22:28:40,0h 0m,小燕(2h3m),2026-01-04 22:29:02
+葛先生,13811638071,3037131328588485,M5,2026-01-04 22:29:47,3h 9m,,2026-01-05 01:44:43
+葛先生,13811638071,3037318211751109,补时长7,2026-01-05 01:39:53,0h 0m,,2026-01-05 01:40:11
+葛先生,13811638071,3038443483466437,A6,2026-01-05 20:44:34,0h 21m,,2026-01-06 02:31:25
+葛先生,13811638071,3038464422284485,M5,2026-01-05 21:05:52,3h 0m,,2026-01-06 02:31:25
+葛先生,13811638071,3038582201207493,S1,2026-01-05 23:05:41,0h 57m,乔西(0h57m) 小燕(0h21m),2026-01-06 02:31:25
+葛先生,13811638071,3038597488594117,补时长7,2026-01-05 23:21:14,0h 0m,小燕(2h35m),2026-01-05 23:22:18
+葛先生,13811638071,3038663145786693,TV,2026-01-06 00:28:01,0h 0m,阿清(1h59m) 小燕(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:51,1h 59m,阿清(1h59m) 小燕(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3039616315803525,A1,2026-01-06 16:37:38,8h 50m,小燕(8h50m),2026-01-07 01:28:11
+葛先生,13811638071,3039824130983749,M7,2026-01-06 20:09:02,3h 22m,小燕(3h22m),2026-01-06 23:36:08
+葛先生,13811638071,3040027900495749,补时长7,2026-01-06 23:36:19,2h 0m,,2026-01-06 23:36:43
+葛先生,13811638071,3040128992692037,TV,2026-01-07 01:19:10,2h 46m,小燕(2h37m),2026-01-07 04:06:07
+葛先生,13811638071,3040137917564805,补时长7,2026-01-07 01:28:14,3h 0m,,2026-01-07 01:28:39
+葛先生,13811638071,3040888209426117,A6,2026-01-07 14:11:29,10h 24m,小燕(10h24m),2026-01-08 05:48:14
+葛先生,13811638071,3041240108402437,VIP5,2026-01-07 20:09:27,1h 11m,小燕(1h11m),2026-01-07 21:21:15
+葛先生,13811638071,3041310718166853,VIP5,2026-01-07 21:21:16,0h 46m,小燕(0h46m) 小燕(0h0m),2026-01-07 22:08:05
+葛先生,13811638071,3041356781012741,VIP5,2026-01-07 22:08:08,1h 2m,小燕(1h1m),2026-01-07 23:10:30
+葛先生,13811638071,3041418120349573,VIP5,2026-01-07 23:10:32,0h 49m,小燕(0h48m),2026-01-08 00:04:02
+葛先生,13811638071,3041502086645445,TV,2026-01-08 00:35:57,5h 11m,小燕(5h11m) 阿清(1h55m),2026-01-08 05:48:14
+葛先生,13811638071,3042589002975045,A6,2026-01-08 19:01:37,4h 9m,小燕(0h0m) 小燕(4h9m) 小燕(0h0m),2026-01-08 23:11:19
+葛先生,13811638071,3042590786307781,S1,2026-01-08 19:03:26,1h 50m,小燕(0h0m),2026-01-08 21:21:03
+葛先生,13811638071,3042699136239301,VIP5,2026-01-08 20:53:38,0h 27m,小燕(2h17m),2026-01-08 21:21:03
+葛先生,13811638071,3042723784541957,TV,2026-01-08 21:18:43,1h 13m,年糕(0h19m) 年糕(0h0m) 年糕(1h28m),2026-01-09 00:02:40
+葛先生,13811638071,3042726147917509,VIP5,2026-01-08 21:21:07,1h 22m,小燕(1h23m),2026-01-08 22:43:49
+葛先生,13811638071,3042796595971845,TV,2026-01-08 22:32:47,1h 28m,年糕(0h19m) 年糕(0h0m) 年糕(1h28m),2026-01-09 00:02:40
+葛先生,13811638071,3042807473456837,VIP5,2026-01-08 22:43:51,0h 26m,小燕(0h26m),2026-01-08 23:11:19
+葛先生,13811638071,3042835118278341,补时长7,2026-01-08 23:11:58,2h 0m,,2026-01-08 23:12:30
+葛先生,13811638071,3042885054465733,补时长7,2026-01-09 00:02:46,0h 0m,,2026-01-09 00:03:28
+葛先生,13811638071,3043910456903429,A6,2026-01-09 17:25:52,7h 34m,小燕(0h0m) 小燕(7h34m) 小燕(0h0m),2026-01-10 01:01:10
+葛先生,13811638071,3044081890182917,S2,2026-01-09 20:20:15,2h 15m,千千(2h13m),2026-01-09 22:38:08
+葛先生,13811638071,3044086761490309,666,2026-01-09 20:25:13,1h 54m,,2026-01-09 22:22:52
+葛先生,13811638071,3044105870411525,M7,2026-01-09 20:44:39,3h 49m,小燕(0h0m) 小燕(3h43m),2026-01-10 00:39:15
+葛先生,13811638071,3044358662178117,补时长6,2026-01-10 01:01:48,4h 0m,,2026-01-10 01:02:29
+葛先生,13811638071,3045217778599621,A6,2026-01-10 15:35:44,7h 33m,小燕(0h0m) 小燕(7h33m),2026-01-10 23:10:26
+葛先生,13811638071,3045663905318661,VIP5,2026-01-10 23:09:34,3h 7m,小燕(3h7m),2026-01-11 02:17:13
+葛先生,13811638071,3045763277047109,补时长5,2026-01-11 00:50:39,2h 2m,,2026-01-11 02:04:36
diff --git a/etl_billiards/reports/assistant_orders_13811638071_2025-11-01.csv b/etl_billiards/reports/assistant_orders_13811638071_2025-11-01.csv
new file mode 100644
index 0000000..bd41001
--- /dev/null
+++ b/etl_billiards/reports/assistant_orders_13811638071_2025-11-01.csv
@@ -0,0 +1,174 @@
+会员名称,会员手机号,订单号,桌台(房间)名称,开始时间,持续时间,助教挂钟信息,结账时间
+葛先生,13811638071,2955001404426373,TV,2025-11-07 22:02:54,6h 17m,周周(6h17m),2025-11-08 04:22:47
+葛先生,13811638071,2957496003612357,B8,2025-11-09 16:20:32,2h 0m,周周(1h57m),2025-11-09 18:27:12
+葛先生,13811638071,2958114600914629,TV,2025-11-09 21:09:49,2h 46m,周周(2h46m) 素素(5h52m),2025-11-10 05:50:36
+葛先生,13811638071,2958114600914629,S1,2025-11-09 23:55:55,2h 53m,,2025-11-10 05:50:36
+葛先生,13811638071,2958114600914629,TV,2025-11-10 02:49:48,2h 59m,周周(2h46m) 素素(5h52m),2025-11-10 05:50:36
+葛先生,13811638071,2963565616418565,VIP5,2025-11-13 23:14:52,3h 31m,年糕(3h28m),2025-11-14 02:46:30
+葛先生,13811638071,2965176087987909,S1,2025-11-15 00:32:38,2h 0m,,2025-11-15 05:16:43
+葛先生,13811638071,2965176087987909,TV,2025-11-15 02:33:07,2h 43m,千千(4h43m) 小燕(2h48m),2025-11-15 05:16:43
+葛先生,13811638071,2966373430363909,888,2025-11-15 22:51:07,3h 25m,柚子(3h25m) 千千(3h21m) 素素(3h12m) 年糕(3h16m) 球球(0h55m),2025-11-16 02:23:36
+葛先生,13811638071,2970984317881221,TV,2025-11-18 21:32:20,7h 7m,,2025-11-19 05:34:46
+葛先生,13811638071,2970984317881221,补时长6,2025-11-19 05:01:34,0h 0m,梦梦(4h27m) 千千(3h7m) 小燕(2h49m),2025-11-19 05:34:46
+葛先生,13811638071,2972114730570373,VIP5,2025-11-19 22:30:59,1h 40m,小燕(1h39m),2025-11-20 02:40:52
+葛先生,13811638071,2972114730570373,TV,2025-11-20 00:11:28,2h 29m,小燕(2h29m),2025-11-20 02:40:52
+葛先生,13811638071,2972261781556293,补时长3,2025-11-20 02:41:04,0h 0m,,2025-11-20 02:41:33
+葛先生,13811638071,2972261781556293,补时长4,2025-11-20 02:41:06,0h 0m,,2025-11-20 02:41:33
+葛先生,13811638071,2973537861161797,TV,2025-11-21 00:19:09,5h 41m,小燕(5h41m) Amy(1h34m),2025-11-21 06:02:46
+葛先生,13811638071,2976440977246341,TV,2025-11-23 01:32:22,5h 53m,小燕(5h53m),2025-11-23 07:26:33
+葛先生,13811638071,2979199778228165,S1,2025-11-24 23:22:58,0h 56m,阿清(0h54m) 小燕(0h9m),2025-11-25 01:10:58
+葛先生,13811638071,2979199778228165,TV,2025-11-25 00:18:45,0h 44m,小燕(0h44m) 阿清(0h44m),2025-11-25 01:10:58
+葛先生,13811638071,2979241077901253,M3,2025-11-25 01:00:46,3h 10m,千千(3h10m) 小燕(3h8m) 阿清(3h8m),2025-11-25 04:13:47
+葛先生,13811638071,2980539547354565,A2,2025-11-25 22:44:25,0h 24m,小燕(0h24m),2025-11-26 05:10:08
+葛先生,13811638071,2980539547354565,VIP5,2025-11-25 23:01:38,6h 7m,小燕(6h0m),2025-11-26 05:10:08
+葛先生,13811638071,2982280563167941,A2,2025-11-27 04:32:42,4h 53m,小燕(4h53m) 阿清(4h49m),2025-11-27 11:33:19
+葛先生,13811638071,2984703823612613,VIP5,2025-11-28 21:37:46,10h 8m,阿清(10h7m) 小燕(8h39m),2025-11-29 07:46:38
+葛先生,13811638071,2986305074877125,VIP5,2025-11-30 00:46:38,6h 16m,小燕(6h15m),2025-11-30 07:06:16
+葛先生,13811638071,2987452433699397,S1,2025-11-30 20:13:48,2h 15m,乔西(2h15m) 小燕(1h59m),2025-11-30 22:29:58
+葛先生,13811638071,2990547445273157,TV,2025-12-03 00:42:12,8h 10m,小燕(8h10m),2025-12-03 08:52:52
+葛先生,13811638071,2991901466284741,A3,2025-12-03 23:39:35,7h 16m,小燕(7h16m),2025-12-04 09:59:55
+葛先生,13811638071,2993421047679685,A3,2025-12-05 01:00:00,0h 25m,,2025-12-05 09:16:58
+葛先生,13811638071,2993421047679685,TV,2025-12-05 01:25:23,7h 50m,小燕(8h16m),2025-12-05 09:16:58
+葛先生,13811638071,2994624795250949,B3,2025-12-05 21:20:49,0h 35m,,2025-12-06 03:19:33
+葛先生,13811638071,2994624795250949,TV,2025-12-05 21:49:54,5h 29m,小燕(5h29m),2025-12-06 03:19:33
+葛先生,13811638071,3003192948659141,TV,2025-12-11 18:23:55,1h 6m,球球(1h6m),2025-12-12 05:16:57
+葛先生,13811638071,3003354125276101,A6,2025-12-11 20:19:55,2h 50m,小燕(2h50m),2025-12-12 01:50:19
+葛先生,13811638071,3003192948659141,888,2025-12-11 23:05:52,6h 0m,小燕(5h56m) 梦梦(2h52m) 涛涛(5h51m) 年糕(2h38m),2025-12-12 05:16:57
+葛先生,13811638071,3003354125276101,A1,2025-12-12 01:49:50,0h 0m,,2025-12-12 01:50:19
+葛先生,13811638071,3003355747341189,补时长4,2025-12-12 01:51:29,0h 1m,,2025-12-12 01:51:48
+葛先生,13811638071,3004579787884613,TV,2025-12-12 22:36:38,8h 10m,小燕(8h10m),2025-12-13 06:47:52
+葛先生,13811638071,3005655255435397,A11,2025-12-13 16:50:40,4h 53m,小燕(4h53m),2025-12-13 21:44:28
+葛先生,13811638071,3005944536778822,补时长7,2025-12-13 21:44:56,2h 0m,,2025-12-13 21:45:20
+葛先生,13811638071,3006295607298309,A1,2025-12-14 03:42:04,0h 43m,小燕(0h43m),2025-12-14 04:26:40
+葛先生,13811638071,3007126951397381,A1,2025-12-14 17:47:45,2h 5m,小燕(2h5m),2025-12-14 19:53:51
+葛先生,13811638071,3007250978523205,补时长5,2025-12-14 19:53:55,0h 1m,,2025-12-14 19:54:17
+葛先生,13811638071,3007446854797445,TV,2025-12-14 23:13:10,5h 57m,小燕(5h57m) 阿清(5h10m),2025-12-15 05:11:18
+葛先生,13811638071,3008834924841285,A1,2025-12-15 22:01:20,2h 19m,小燕(2h19m),2025-12-16 02:42:42
+葛先生,13811638071,3008834924841285,S1,2025-12-15 22:45:11,3h 55m,苏苏(2h28m),2025-12-16 02:42:42
+葛先生,13811638071,3009076506036165,A2,2025-12-16 02:50:56,3h 40m,小燕(3h39m),2025-12-16 06:32:44
+葛先生,13811638071,3009492999244293,补时长7,2025-12-16 09:54:37,3h 0m,,2025-12-16 09:54:56
+葛先生,13811638071,3010218131671557,A1,2025-12-16 22:12:16,3h 18m,小燕(3h18m) 阿清(2h43m),2025-12-17 01:31:11
+葛先生,13811638071,3011552955975237,A1,2025-12-17 19:25:16,1h 34m,小燕(1h34m),2025-12-17 22:04:09
+葛先生,13811638071,3011552955975237,C2,2025-12-17 20:50:07,1h 13m,小燕(1h3m),2025-12-17 22:04:09
+葛先生,13811638071,3011630421837381,A18,2025-12-17 22:08:55,3h 3m,小燕(3h3m),2025-12-18 01:12:30
+葛先生,13811638071,3012931996487173,TV,2025-12-18 20:12:57,5h 38m,小燕(5h38m),2025-12-19 01:53:16
+葛先生,13811638071,3013266727145349,补时长5,2025-12-19 01:53:27,2h 0m,,2025-12-19 01:53:55
+葛先生,13811638071,3013302603681669,A6,2025-12-19 02:29:57,0h 30m,小燕(0h29m),2025-12-19 03:00:10
+葛先生,13811638071,3013331369283205,A1,2025-12-19 02:59:12,0h 18m,,2025-12-19 02:59:41
+葛先生,13811638071,3014479760183173,A6,2025-12-19 17:07:12,11h 18m,小燕(11h18m) 阿清(2h0m),2025-12-20 06:59:01
+葛先生,13811638071,3014479760183173,TV,2025-12-19 22:27:25,8h 31m,小燕(2h53m) 阿清(8h22m),2025-12-20 06:59:01
+葛先生,13811638071,3015171680994757,补时长7,2025-12-20 10:11:16,3h 0m,,2025-12-20 10:11:36
+葛先生,13811638071,3015904480560645,S2,2025-12-20 21:38:55,0h 56m,球球(0h56m),2025-12-20 22:38:26
+葛先生,13811638071,3015928035247749,S1,2025-12-20 21:47:59,1h 12m,小燕(1h12m),2025-12-20 23:01:49
+葛先生,13811638071,3015974337283525,补时长6,2025-12-20 23:47:46,3h 0m,,2025-12-20 23:48:13
+葛先生,13811638071,3015974988367429,C4,2025-12-20 23:48:26,4h 28m,小燕(4h28m),2025-12-21 04:17:32
+葛先生,13811638071,3016300766643845,TV,2025-12-21 05:19:50,0h 56m,小燕(0h56m),2025-12-21 06:16:53
+葛先生,13811638071,3016653147375173,补时长7,2025-12-21 11:18:18,2h 0m,,2025-12-21 11:18:40
+葛先生,13811638071,3017225201927749,S1,2025-12-21 21:00:13,1h 28m,,2025-12-21 22:30:16
+葛先生,13811638071,3017273506465285,C5,2025-12-21 21:49:21,1h 24m,千千(1h12m),2025-12-21 23:45:38
+葛先生,13811638071,3017388287231429,补时长6,2025-12-21 23:46:07,0h 0m,,2025-12-21 23:46:27
+葛先生,13811638071,3017486080099845,A1,2025-12-22 01:25:36,1h 49m,小燕(1h49m),2025-12-22 03:15:17
+葛先生,13811638071,3017593957697157,补时长6,2025-12-22 03:15:20,0h 0m,,2025-12-22 03:15:37
+葛先生,13811638071,3017596515419717,A1,2025-12-22 03:17:56,3h 49m,小燕(3h49m),2025-12-22 07:08:11
+葛先生,13811638071,3018642766775813,S1,2025-12-22 21:02:14,1h 7m,小燕(1h7m),2025-12-22 22:10:33
+葛先生,13811638071,3018644316587589,补时长7,2025-12-22 21:03:49,0h 0m,,2025-12-22 21:04:09
+葛先生,13811638071,3018709942093445,S1,2025-12-22 22:10:34,0h 43m,小燕(0h43m),2025-12-22 22:54:21
+葛先生,13811638071,3018710150219205,补时长6,2025-12-22 22:10:47,0h 0m,,2025-12-22 22:11:08
+葛先生,13811638071,3018753009468933,S1,2025-12-22 22:54:23,1h 3m,小燕(1h3m),2025-12-22 23:58:44
+葛先生,13811638071,3018766856488389,补时长6,2025-12-22 23:08:28,0h 0m,,2025-12-22 23:08:51
+葛先生,13811638071,3018816489850309,补时长7,2025-12-22 23:58:58,0h 0m,,2025-12-22 23:59:34
+葛先生,13811638071,3018826595370437,M7,2025-12-23 00:09:14,4h 0m,小燕(3h59m),2025-12-23 04:23:37
+葛先生,13811638071,3019076971070917,补时长6,2025-12-23 04:23:56,2h 0m,,2025-12-23 04:24:21
+葛先生,13811638071,3019077416650181,A1,2025-12-23 04:24:23,3h 7m,小燕(3h7m),2025-12-23 07:32:22
+葛先生,13811638071,3019262758979077,补时长6,2025-12-23 07:32:56,0h 0m,,2025-12-23 07:34:10
+葛先生,13811638071,3020101562009093,A6,2025-12-23 21:46:12,10h 2m,小燕(10h1m),2025-12-24 07:48:47
+葛先生,13811638071,3020694538569157,补时长5,2025-12-24 07:49:25,3h 0m,,2025-12-24 07:49:46
+葛先生,13811638071,3021420856576006,S1,2025-12-24 20:08:16,1h 22m,小燕(1h22m),2025-12-24 21:30:46
+葛先生,13811638071,3021501988194373,S1,2025-12-24 21:30:47,1h 50m,小燕(1h49m),2025-12-24 23:21:38
+葛先生,13811638071,3021610987734853,S1,2025-12-24 23:21:40,2h 21m,小燕(2h21m),2025-12-25 01:43:51
+葛先生,13811638071,3021770635823109,A6,2025-12-25 02:04:04,7h 56m,小燕(7h56m),2025-12-25 12:08:55
+葛先生,13811638071,3022365496854533,补时长6,2025-12-25 12:09:12,4h 0m,,2025-12-25 12:09:46
+葛先生,13811638071,3022873228429253,S1,2025-12-25 20:45:41,1h 55m,小燕(1h55m),2025-12-25 22:42:03
+葛先生,13811638071,3022987729340421,S1,2025-12-25 22:42:10,1h 9m,小燕(1h9m),2025-12-25 23:52:24
+葛先生,13811638071,3023056813000773,S1,2025-12-25 23:52:26,0h 58m,小燕(0h58m),2025-12-26 00:51:10
+葛先生,13811638071,3023057336322053,补时长5,2025-12-25 23:52:58,0h 0m,,2025-12-25 23:53:18
+葛先生,13811638071,3023118312458181,A6,2025-12-26 00:55:00,5h 59m,小燕(5h59m),2025-12-26 06:55:32
+葛先生,13811638071,3024330328901573,C1,2025-12-26 21:27:56,3h 14m,小燕(3h14m),2025-12-27 00:42:31
+葛先生,13811638071,3024521672149061,A6,2025-12-27 00:42:34,4h 56m,小燕(4h56m),2025-12-27 05:43:00
+葛先生,13811638071,3024522484762565,补时长6,2025-12-27 00:43:24,2h 0m,,2025-12-27 00:43:51
+葛先生,13811638071,3025075373508677,补时长7,2025-12-27 10:05:50,2h 0m,,2025-12-27 10:06:18
+葛先生,13811638071,3025697485457477,A12,2025-12-27 20:38:40,0h 24m,小燕(0h24m),2025-12-27 21:03:38
+葛先生,13811638071,3025926993020741,A18,2025-12-28 00:32:08,3h 59m,小燕(3h58m),2025-12-28 04:31:30
+葛先生,13811638071,3026162441734149,补时长5,2025-12-28 04:31:39,1h 40m,,2025-12-28 04:32:29
+葛先生,13811638071,3027018732144709,A8,2025-12-28 19:02:43,1h 5m,小燕(1h5m),2025-12-28 20:08:25
+葛先生,13811638071,3027082894100549,S1,2025-12-28 20:07:59,0h 47m,小燕(0h47m),2025-12-28 20:55:54
+葛先生,13811638071,3027086248364101,A8,2025-12-28 20:11:24,0h 32m,,2025-12-28 20:11:45
+葛先生,13811638071,3027171803039749,S1,2025-12-28 20:55:56,0h 42m,,2025-12-28 22:48:42
+葛先生,13811638071,3027130329974789,A6,2025-12-28 20:56:14,0h 32m,,2025-12-28 20:56:31
+葛先生,13811638071,3027171803039749,VIP5,2025-12-28 21:38:25,1h 9m,小燕(1h52m),2025-12-28 22:48:42
+葛先生,13811638071,3027240911620101,VIP5,2025-12-28 22:48:44,0h 42m,小燕(0h42m),2025-12-28 23:32:00
+葛先生,13811638071,3027279097726917,A1,2025-12-28 23:23:12,0h 4m,,2025-12-29 00:45:50
+葛先生,13811638071,3027279097726917,C2,2025-12-28 23:27:34,1h 17m,婉婉(1h17m),2025-12-29 00:45:50
+葛先生,13811638071,3027283487705029,VIP5,2025-12-28 23:32:02,1h 38m,小燕(1h38m),2025-12-29 01:10:27
+葛先生,13811638071,3027381047756741,补时长7,2025-12-29 01:11:17,0h 0m,,2025-12-29 01:11:47
+葛先生,13811638071,3027494215747397,A1,2025-12-29 03:06:24,0h 0m,小燕(1h50m),2025-12-29 03:06:51
+葛先生,13811638071,3027520016877573,补时长5,2025-12-29 03:32:39,1h 40m,,2025-12-29 03:33:33
+葛先生,13811638071,3028365240272837,A6,2025-12-29 17:52:27,2h 3m,小燕(2h3m),2025-12-29 19:58:42
+葛先生,13811638071,3028488531724357,M5,2025-12-29 19:57:52,3h 3m,小燕(3h3m),2025-12-29 23:04:58
+葛先生,13811638071,3028489795159877,A6,2025-12-29 19:59:09,1h 2m,,2025-12-29 19:59:31
+葛先生,13811638071,3028620706809861,VIP5,2025-12-29 22:12:19,1h 2m,小柔(1h2m) 小燕(0h6m),2025-12-29 23:16:04
+葛先生,13811638071,3028672505759557,补时长7,2025-12-29 23:05:01,0h 0m,,2025-12-29 23:05:28
+葛先生,13811638071,3028796631942981,A1,2025-12-30 01:11:17,0h 0m,小燕(1h12m),2025-12-30 01:12:20
+葛先生,13811638071,3028797785933637,补时长6,2025-12-30 01:12:28,0h 0m,,2025-12-30 01:12:43
+葛先生,13811638071,3028798611277893,A6,2025-12-30 01:13:18,0h 51m,小燕(0h50m),2025-12-30 02:04:34
+葛先生,13811638071,3029823520163653,A6,2025-12-30 18:35:53,1h 30m,小燕(1h30m),2025-12-30 20:06:17
+葛先生,13811638071,3029912671930309,A2,2025-12-30 20:06:35,0h 45m,,2025-12-30 20:07:12
+葛先生,13811638071,3029920336283461,S1,2025-12-30 20:14:23,1h 9m,小燕(1h8m),2025-12-30 21:26:01
+葛先生,13811638071,3029953608239109,S3,2025-12-30 20:48:13,0h 54m,,2025-12-30 21:43:22
+葛先生,13811638071,3029990793086789,S1,2025-12-30 21:26:03,1h 22m,小燕(1h1m) 阿清(0h20m),2025-12-30 22:48:21
+葛先生,13811638071,3029991615416389,A6,2025-12-30 21:26:53,0h 50m,,2025-12-30 21:27:30
+葛先生,13811638071,3030051846162437,A6,2025-12-30 22:28:09,1h 35m,小燕(1h13m),2025-12-31 00:03:58
+葛先生,13811638071,3030071938451269,S1,2025-12-30 22:48:36,0h 45m,阿清(0h45m),2025-12-30 23:34:52
+葛先生,13811638071,3030329100781637,补时长2,2025-12-31 03:10:12,0h 1m,,2025-12-31 03:10:58
+葛先生,13811638071,3031047867485317,VIP1,2025-12-31 15:21:22,2h 15m,小燕(2h15m),2025-12-31 18:30:37
+葛先生,13811638071,3031246638532229,补时长2,2025-12-31 18:43:30,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3031246638532229,补时长3,2025-12-31 18:43:34,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3036870032656645,A6,2026-01-04 18:03:58,2h 15m,小燕(2h15m),2026-01-04 20:20:13
+葛先生,13811638071,3037004116691653,补时长7,2026-01-04 20:20:22,0h 0m,,2026-01-04 20:20:58
+葛先生,13811638071,3037130243574469,A7,2026-01-04 22:28:40,0h 0m,小燕(2h3m),2026-01-04 22:29:02
+葛先生,13811638071,3037131328588485,M5,2026-01-04 22:29:47,3h 9m,,2026-01-05 01:44:43
+葛先生,13811638071,3037318211751109,补时长7,2026-01-05 01:39:53,0h 0m,,2026-01-05 01:40:11
+葛先生,13811638071,3038663954582853,A6,2026-01-05 20:44:34,0h 21m,,2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,M5,2026-01-05 21:05:52,3h 0m,,2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,S1,2026-01-05 23:05:41,0h 57m,乔西(0h57m) 小燕(0h21m),2026-01-06 02:31:25
+葛先生,13811638071,3038597488594117,补时长7,2026-01-05 23:21:14,0h 0m,小燕(2h35m),2026-01-05 23:22:18
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:01,0h 0m,小燕(1h59m) 阿清(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:51,1h 59m,小燕(1h59m) 阿清(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3039616315803525,A1,2026-01-06 16:37:38,8h 50m,小燕(8h50m),2026-01-07 01:28:11
+葛先生,13811638071,3039824130983749,M7,2026-01-06 20:09:02,3h 22m,小燕(3h22m),2026-01-06 23:36:08
+葛先生,13811638071,3040027900495749,补时长7,2026-01-06 23:36:19,2h 0m,,2026-01-06 23:36:43
+葛先生,13811638071,3040128992692037,TV,2026-01-07 01:19:10,2h 46m,小燕(2h37m),2026-01-07 04:06:07
+葛先生,13811638071,3040137917564805,补时长7,2026-01-07 01:28:14,3h 0m,,2026-01-07 01:28:39
+葛先生,13811638071,3041502086645445,A6,2026-01-07 14:11:29,10h 24m,小燕(10h24m),2026-01-08 05:48:14
+葛先生,13811638071,3041240108402437,VIP5,2026-01-07 20:09:27,1h 11m,小燕(1h11m),2026-01-07 21:21:15
+葛先生,13811638071,3041310718166853,VIP5,2026-01-07 21:21:16,0h 46m,小燕(0h46m),2026-01-07 22:08:05
+葛先生,13811638071,3041356781012741,VIP5,2026-01-07 22:08:08,1h 2m,小燕(1h1m),2026-01-07 23:10:30
+葛先生,13811638071,3041418120349573,VIP5,2026-01-07 23:10:32,0h 49m,小燕(0h48m),2026-01-08 00:04:02
+葛先生,13811638071,3041502086645445,TV,2026-01-08 00:35:57,5h 11m,阿清(1h55m) 小燕(5h11m),2026-01-08 05:48:14
+葛先生,13811638071,3042589002975045,A6,2026-01-08 19:01:37,4h 9m,小燕(6h9m),2026-01-08 23:11:19
+葛先生,13811638071,3042699136239301,S1,2026-01-08 19:03:26,1h 50m,,2026-01-08 21:21:03
+葛先生,13811638071,3042699136239301,VIP5,2026-01-08 20:53:38,0h 27m,小燕(2h17m),2026-01-08 21:21:03
+葛先生,13811638071,3042796595971845,TV,2026-01-08 21:18:43,1h 13m,年糕(1h47m),2026-01-09 00:02:40
+葛先生,13811638071,3042726147917509,VIP5,2026-01-08 21:21:07,1h 22m,小燕(1h23m),2026-01-08 22:43:49
+葛先生,13811638071,3042796595971845,TV,2026-01-08 22:32:47,1h 28m,年糕(1h47m),2026-01-09 00:02:40
+葛先生,13811638071,3042589002975045,VIP5,2026-01-08 22:43:51,0h 26m,小燕(0h26m),2026-01-08 23:11:19
+葛先生,13811638071,3042835118278341,补时长7,2026-01-08 23:11:58,2h 0m,,2026-01-08 23:12:30
+葛先生,13811638071,3042885054465733,补时长7,2026-01-09 00:02:46,0h 0m,,2026-01-09 00:03:28
+葛先生,13811638071,3043910456903429,A6,2026-01-09 17:25:52,7h 34m,小燕(10h34m),2026-01-10 01:01:10
+葛先生,13811638071,3044081890182917,S2,2026-01-09 20:20:15,2h 15m,千千(2h13m),2026-01-09 22:38:08
+葛先生,13811638071,3044086761490309,666,2026-01-09 20:25:13,1h 54m,,2026-01-09 22:22:52
+葛先生,13811638071,3044105870411525,M7,2026-01-09 20:44:39,3h 49m,小燕(3h43m),2026-01-10 00:39:15
+葛先生,13811638071,3044358662178117,补时长6,2026-01-10 01:01:48,4h 0m,,2026-01-10 01:02:29
+葛先生,13811638071,3045217778599621,A6,2026-01-10 15:35:44,7h 33m,小燕(7h33m),2026-01-10 23:10:26
+葛先生,13811638071,3045663905318661,VIP5,2026-01-10 23:09:34,3h 7m,小燕(3h7m),2026-01-11 02:17:13
+葛先生,13811638071,3045763277047109,补时长5,2026-01-11 00:50:39,2h 2m,,2026-01-11 02:04:36
diff --git a/etl_billiards/reports/assistant_orders_13811638071_2025-11-01_no_table.csv b/etl_billiards/reports/assistant_orders_13811638071_2025-11-01_no_table.csv
new file mode 100644
index 0000000..73befd5
--- /dev/null
+++ b/etl_billiards/reports/assistant_orders_13811638071_2025-11-01_no_table.csv
@@ -0,0 +1,27 @@
+会员名称,会员手机号,订单号,桌台(房间)名称,开始时间,持续时间,助教挂钟信息,结账时间
+葛先生,13811638071,2957821891038725,,2025-11-09 21:52:03,0h 0m,,2025-11-09 21:52:08
+葛先生,13811638071,2966177428162245,,2025-11-15 19:31:45,0h 0m,,2025-11-15 19:31:50
+葛先生,13811638071,2980458746317189,,2025-11-25 21:39:27,0h 0m,,2025-11-25 21:39:32
+葛先生,13811638071,2982035921635973,,2025-11-27 00:23:50,0h 0m,,2025-11-27 00:23:54
+葛先生,13811638071,2986261249411781,,2025-11-30 00:02:04,0h 0m,,2025-11-30 00:02:10
+葛先生,13811638071,2987682979566149,,2025-12-01 00:08:19,0h 0m,,2025-12-01 00:08:25
+葛先生,13811638071,2996398357319941,,2025-12-07 03:54:04,0h 0m,,2025-12-07 03:54:45
+葛先生,13811638071,3000142759381509,,2025-12-09 19:23:04,0h 0m,,2025-12-09 19:23:08
+葛先生,13811638071,3000218457131525,,2025-12-09 20:40:04,0h 0m,,2025-12-09 20:40:07
+葛先生,13811638071,3000309702920709,,2025-12-09 22:12:54,0h 1m,,2025-12-09 22:14:06
+葛先生,13811638071,3000373824244293,,2025-12-09 23:18:07,0h 0m,,2025-12-09 23:18:10
+葛先生,13811638071,3000377913346565,,2025-12-09 23:22:17,0h 0m,,2025-12-09 23:22:22
+葛先生,13811638071,3000415061690757,,2025-12-10 00:00:04,0h 0m,,2025-12-10 00:00:08
+葛先生,13811638071,3003030187398085,,2025-12-11 20:20:19,0h 0m,,2025-12-11 20:20:22
+葛先生,13811638071,3005540084271109,,2025-12-13 14:53:31,0h 0m,,2025-12-13 14:53:34
+葛先生,13811638071,3005540596467845,,2025-12-13 14:54:02,0h 0m,,2025-12-13 14:54:03
+葛先生,13811638071,3005709583894533,,2025-12-13 17:45:56,0h 0m,,2025-12-13 17:45:58
+葛先生,13811638071,3008791223945669,,2025-12-15 22:00:44,0h 0m,,2025-12-15 22:00:48
+葛先生,13811638071,3010440130430917,,2025-12-17 01:58:06,0h 0m,,2025-12-17 01:58:11
+葛先生,13811638071,3014246545706757,,2025-12-19 18:30:11,0h 0m,,2025-12-19 18:30:15
+葛先生,13811638071,3017228572607941,,2025-12-21 21:03:39,0h 0m,,2025-12-21 21:03:41
+葛先生,13811638071,3025720252254149,,2025-12-27 21:01:50,0h 0m,,2025-12-27 21:01:53
+葛先生,13811638071,3041096056031110,,2026-01-07 17:42:55,0h 0m,,2026-01-07 17:43:01
+葛先生,13811638071,3045359793473221,,2026-01-10 18:00:13,0h 0m,,2026-01-10 18:00:16
+葛先生,13811638071,3045651477251973,,2026-01-10 22:56:56,0h 0m,,2026-01-10 22:56:58
+葛先生,13811638071,3047065961137861,,2026-01-11 22:55:49,0h 0m,,2026-01-11 22:55:51
diff --git a/etl_billiards/reports/assistant_orders_13811638071_2025-11-14.csv b/etl_billiards/reports/assistant_orders_13811638071_2025-11-14.csv
new file mode 100644
index 0000000..10fb192
--- /dev/null
+++ b/etl_billiards/reports/assistant_orders_13811638071_2025-11-14.csv
@@ -0,0 +1,168 @@
+会员名称,会员手机号,订单号,桌台(房间)名称,开始时间,持续时间,助教挂钟信息,结账时间
+葛先生,13811638071,2965176087987909,S1,2025-11-15 00:32:38,2h 0m,,2025-11-15 05:16:43
+葛先生,13811638071,2965176087987909,TV,2025-11-15 02:33:07,2h 43m,千千(4h43m) 小燕(2h48m),2025-11-15 05:16:43
+葛先生,13811638071,2966373430363909,888,2025-11-15 22:51:07,3h 25m,柚子(3h25m) 千千(3h21m) 素素(3h12m) 年糕(3h16m) 球球(0h55m),2025-11-16 02:23:36
+葛先生,13811638071,2970984317881221,TV,2025-11-18 21:32:20,7h 7m,,2025-11-19 05:34:46
+葛先生,13811638071,2970984317881221,补时长6,2025-11-19 05:01:34,0h 0m,梦梦(4h27m) 千千(3h7m) 小燕(2h49m),2025-11-19 05:34:46
+葛先生,13811638071,2972114730570373,VIP5,2025-11-19 22:30:59,1h 40m,小燕(1h39m),2025-11-20 02:40:52
+葛先生,13811638071,2972114730570373,TV,2025-11-20 00:11:28,2h 29m,小燕(2h29m),2025-11-20 02:40:52
+葛先生,13811638071,2972261781556293,补时长3,2025-11-20 02:41:04,0h 0m,,2025-11-20 02:41:33
+葛先生,13811638071,2972261781556293,补时长4,2025-11-20 02:41:06,0h 0m,,2025-11-20 02:41:33
+葛先生,13811638071,2973537861161797,TV,2025-11-21 00:19:09,5h 41m,小燕(5h41m) Amy(1h34m),2025-11-21 06:02:46
+葛先生,13811638071,2976440977246341,TV,2025-11-23 01:32:22,5h 53m,小燕(5h53m),2025-11-23 07:26:33
+葛先生,13811638071,2979199778228165,S1,2025-11-24 23:22:58,0h 56m,阿清(0h54m) 小燕(0h9m),2025-11-25 01:10:58
+葛先生,13811638071,2979199778228165,TV,2025-11-25 00:18:45,0h 44m,小燕(0h44m) 阿清(0h44m),2025-11-25 01:10:58
+葛先生,13811638071,2979241077901253,M3,2025-11-25 01:00:46,3h 10m,千千(3h10m) 小燕(3h8m) 阿清(3h8m),2025-11-25 04:13:47
+葛先生,13811638071,2980539547354565,A2,2025-11-25 22:44:25,0h 24m,小燕(0h24m),2025-11-26 05:10:08
+葛先生,13811638071,2980539547354565,VIP5,2025-11-25 23:01:38,6h 7m,小燕(6h0m),2025-11-26 05:10:08
+葛先生,13811638071,2982280563167941,A2,2025-11-27 04:32:42,4h 53m,小燕(4h53m) 阿清(4h49m),2025-11-27 11:33:19
+葛先生,13811638071,2984703823612613,VIP5,2025-11-28 21:37:46,10h 8m,阿清(10h7m) 小燕(8h39m),2025-11-29 07:46:38
+葛先生,13811638071,2986305074877125,VIP5,2025-11-30 00:46:38,6h 16m,小燕(6h15m),2025-11-30 07:06:16
+葛先生,13811638071,2987452433699397,S1,2025-11-30 20:13:48,2h 15m,乔西(2h15m) 小燕(1h59m),2025-11-30 22:29:58
+葛先生,13811638071,2990547445273157,TV,2025-12-03 00:42:12,8h 10m,小燕(8h10m),2025-12-03 08:52:52
+葛先生,13811638071,2991901466284741,A3,2025-12-03 23:39:35,7h 16m,小燕(7h16m),2025-12-04 09:59:55
+葛先生,13811638071,2993421047679685,A3,2025-12-05 01:00:00,0h 25m,,2025-12-05 09:16:58
+葛先生,13811638071,2993421047679685,TV,2025-12-05 01:25:23,7h 50m,小燕(8h16m),2025-12-05 09:16:58
+葛先生,13811638071,2994624795250949,B3,2025-12-05 21:20:49,0h 35m,,2025-12-06 03:19:33
+葛先生,13811638071,2994624795250949,TV,2025-12-05 21:49:54,5h 29m,小燕(5h29m),2025-12-06 03:19:33
+葛先生,13811638071,3003192948659141,TV,2025-12-11 18:23:55,1h 6m,球球(1h6m),2025-12-12 05:16:57
+葛先生,13811638071,3003354125276101,A6,2025-12-11 20:19:55,2h 50m,小燕(2h50m),2025-12-12 01:50:19
+葛先生,13811638071,3003192948659141,888,2025-12-11 23:05:52,6h 0m,小燕(5h56m) 梦梦(2h52m) 涛涛(5h51m) 年糕(2h38m),2025-12-12 05:16:57
+葛先生,13811638071,3003354125276101,A1,2025-12-12 01:49:50,0h 0m,,2025-12-12 01:50:19
+葛先生,13811638071,3003355747341189,补时长4,2025-12-12 01:51:29,0h 1m,,2025-12-12 01:51:48
+葛先生,13811638071,3004579787884613,TV,2025-12-12 22:36:38,8h 10m,小燕(8h10m),2025-12-13 06:47:52
+葛先生,13811638071,3005655255435397,A11,2025-12-13 16:50:40,4h 53m,小燕(4h53m),2025-12-13 21:44:28
+葛先生,13811638071,3005944536778822,补时长7,2025-12-13 21:44:56,2h 0m,,2025-12-13 21:45:20
+葛先生,13811638071,3006295607298309,A1,2025-12-14 03:42:04,0h 43m,小燕(0h43m),2025-12-14 04:26:40
+葛先生,13811638071,3007126951397381,A1,2025-12-14 17:47:45,2h 5m,小燕(2h5m),2025-12-14 19:53:51
+葛先生,13811638071,3007250978523205,补时长5,2025-12-14 19:53:55,0h 1m,,2025-12-14 19:54:17
+葛先生,13811638071,3007446854797445,TV,2025-12-14 23:13:10,5h 57m,小燕(5h57m) 阿清(5h10m),2025-12-15 05:11:18
+葛先生,13811638071,3008834924841285,A1,2025-12-15 22:01:20,2h 19m,小燕(2h19m),2025-12-16 02:42:42
+葛先生,13811638071,3008834924841285,S1,2025-12-15 22:45:11,3h 55m,苏苏(2h28m),2025-12-16 02:42:42
+葛先生,13811638071,3009076506036165,A2,2025-12-16 02:50:56,3h 40m,小燕(3h39m),2025-12-16 06:32:44
+葛先生,13811638071,3009492999244293,补时长7,2025-12-16 09:54:37,3h 0m,,2025-12-16 09:54:56
+葛先生,13811638071,3010218131671557,A1,2025-12-16 22:12:16,3h 18m,小燕(3h18m) 阿清(2h43m),2025-12-17 01:31:11
+葛先生,13811638071,3011552955975237,A1,2025-12-17 19:25:16,1h 34m,小燕(1h34m),2025-12-17 22:04:09
+葛先生,13811638071,3011552955975237,C2,2025-12-17 20:50:07,1h 13m,小燕(1h3m),2025-12-17 22:04:09
+葛先生,13811638071,3011630421837381,A18,2025-12-17 22:08:55,3h 3m,小燕(3h3m),2025-12-18 01:12:30
+葛先生,13811638071,3012931996487173,TV,2025-12-18 20:12:57,5h 38m,小燕(5h38m),2025-12-19 01:53:16
+葛先生,13811638071,3013266727145349,补时长5,2025-12-19 01:53:27,2h 0m,,2025-12-19 01:53:55
+葛先生,13811638071,3013302603681669,A6,2025-12-19 02:29:57,0h 30m,小燕(0h29m),2025-12-19 03:00:10
+葛先生,13811638071,3013331369283205,A1,2025-12-19 02:59:12,0h 18m,,2025-12-19 02:59:41
+葛先生,13811638071,3014479760183173,A6,2025-12-19 17:07:12,11h 18m,小燕(11h18m) 阿清(2h0m),2025-12-20 06:59:01
+葛先生,13811638071,3014479760183173,TV,2025-12-19 22:27:25,8h 31m,小燕(2h53m) 阿清(8h22m),2025-12-20 06:59:01
+葛先生,13811638071,3015171680994757,补时长7,2025-12-20 10:11:16,3h 0m,,2025-12-20 10:11:36
+葛先生,13811638071,3015904480560645,S2,2025-12-20 21:38:55,0h 56m,球球(0h56m),2025-12-20 22:38:26
+葛先生,13811638071,3015928035247749,S1,2025-12-20 21:47:59,1h 12m,小燕(1h12m),2025-12-20 23:01:49
+葛先生,13811638071,3015974337283525,补时长6,2025-12-20 23:47:46,3h 0m,,2025-12-20 23:48:13
+葛先生,13811638071,3015974988367429,C4,2025-12-20 23:48:26,4h 28m,小燕(4h28m),2025-12-21 04:17:32
+葛先生,13811638071,3016300766643845,TV,2025-12-21 05:19:50,0h 56m,小燕(0h56m),2025-12-21 06:16:53
+葛先生,13811638071,3016653147375173,补时长7,2025-12-21 11:18:18,2h 0m,,2025-12-21 11:18:40
+葛先生,13811638071,3017225201927749,S1,2025-12-21 21:00:13,1h 28m,,2025-12-21 22:30:16
+葛先生,13811638071,3017273506465285,C5,2025-12-21 21:49:21,1h 24m,千千(1h12m),2025-12-21 23:45:38
+葛先生,13811638071,3017388287231429,补时长6,2025-12-21 23:46:07,0h 0m,,2025-12-21 23:46:27
+葛先生,13811638071,3017486080099845,A1,2025-12-22 01:25:36,1h 49m,小燕(1h49m),2025-12-22 03:15:17
+葛先生,13811638071,3017593957697157,补时长6,2025-12-22 03:15:20,0h 0m,,2025-12-22 03:15:37
+葛先生,13811638071,3017596515419717,A1,2025-12-22 03:17:56,3h 49m,小燕(3h49m),2025-12-22 07:08:11
+葛先生,13811638071,3018642766775813,S1,2025-12-22 21:02:14,1h 7m,小燕(1h7m),2025-12-22 22:10:33
+葛先生,13811638071,3018644316587589,补时长7,2025-12-22 21:03:49,0h 0m,,2025-12-22 21:04:09
+葛先生,13811638071,3018709942093445,S1,2025-12-22 22:10:34,0h 43m,小燕(0h43m),2025-12-22 22:54:21
+葛先生,13811638071,3018710150219205,补时长6,2025-12-22 22:10:47,0h 0m,,2025-12-22 22:11:08
+葛先生,13811638071,3018753009468933,S1,2025-12-22 22:54:23,1h 3m,小燕(1h3m),2025-12-22 23:58:44
+葛先生,13811638071,3018766856488389,补时长6,2025-12-22 23:08:28,0h 0m,,2025-12-22 23:08:51
+葛先生,13811638071,3018816489850309,补时长7,2025-12-22 23:58:58,0h 0m,,2025-12-22 23:59:34
+葛先生,13811638071,3018826595370437,M7,2025-12-23 00:09:14,4h 0m,小燕(3h59m),2025-12-23 04:23:37
+葛先生,13811638071,3019076971070917,补时长6,2025-12-23 04:23:56,2h 0m,,2025-12-23 04:24:21
+葛先生,13811638071,3019077416650181,A1,2025-12-23 04:24:23,3h 7m,小燕(3h7m),2025-12-23 07:32:22
+葛先生,13811638071,3019262758979077,补时长6,2025-12-23 07:32:56,0h 0m,,2025-12-23 07:34:10
+葛先生,13811638071,3020101562009093,A6,2025-12-23 21:46:12,10h 2m,小燕(10h1m),2025-12-24 07:48:47
+葛先生,13811638071,3020694538569157,补时长5,2025-12-24 07:49:25,3h 0m,,2025-12-24 07:49:46
+葛先生,13811638071,3021420856576006,S1,2025-12-24 20:08:16,1h 22m,小燕(1h22m),2025-12-24 21:30:46
+葛先生,13811638071,3021501988194373,S1,2025-12-24 21:30:47,1h 50m,小燕(1h49m),2025-12-24 23:21:38
+葛先生,13811638071,3021610987734853,S1,2025-12-24 23:21:40,2h 21m,小燕(2h21m),2025-12-25 01:43:51
+葛先生,13811638071,3021770635823109,A6,2025-12-25 02:04:04,7h 56m,小燕(7h56m),2025-12-25 12:08:55
+葛先生,13811638071,3022365496854533,补时长6,2025-12-25 12:09:12,4h 0m,,2025-12-25 12:09:46
+葛先生,13811638071,3022873228429253,S1,2025-12-25 20:45:41,1h 55m,小燕(1h55m),2025-12-25 22:42:03
+葛先生,13811638071,3022987729340421,S1,2025-12-25 22:42:10,1h 9m,小燕(1h9m),2025-12-25 23:52:24
+葛先生,13811638071,3023056813000773,S1,2025-12-25 23:52:26,0h 58m,小燕(0h58m),2025-12-26 00:51:10
+葛先生,13811638071,3023057336322053,补时长5,2025-12-25 23:52:58,0h 0m,,2025-12-25 23:53:18
+葛先生,13811638071,3023118312458181,A6,2025-12-26 00:55:00,5h 59m,小燕(5h59m),2025-12-26 06:55:32
+葛先生,13811638071,3024330328901573,C1,2025-12-26 21:27:56,3h 14m,小燕(3h14m),2025-12-27 00:42:31
+葛先生,13811638071,3024521672149061,A6,2025-12-27 00:42:34,4h 56m,小燕(4h56m),2025-12-27 05:43:00
+葛先生,13811638071,3024522484762565,补时长6,2025-12-27 00:43:24,2h 0m,,2025-12-27 00:43:51
+葛先生,13811638071,3025075373508677,补时长7,2025-12-27 10:05:50,2h 0m,,2025-12-27 10:06:18
+葛先生,13811638071,3025697485457477,A12,2025-12-27 20:38:40,0h 24m,小燕(0h24m),2025-12-27 21:03:38
+葛先生,13811638071,3025926993020741,A18,2025-12-28 00:32:08,3h 59m,小燕(3h58m),2025-12-28 04:31:30
+葛先生,13811638071,3026162441734149,补时长5,2025-12-28 04:31:39,1h 40m,,2025-12-28 04:32:29
+葛先生,13811638071,3027018732144709,A8,2025-12-28 19:02:43,1h 5m,小燕(1h5m),2025-12-28 20:08:25
+葛先生,13811638071,3027082894100549,S1,2025-12-28 20:07:59,0h 47m,小燕(0h47m),2025-12-28 20:55:54
+葛先生,13811638071,3027086248364101,A8,2025-12-28 20:11:24,0h 32m,,2025-12-28 20:11:45
+葛先生,13811638071,3027171803039749,S1,2025-12-28 20:55:56,0h 42m,,2025-12-28 22:48:42
+葛先生,13811638071,3027130329974789,A6,2025-12-28 20:56:14,0h 32m,,2025-12-28 20:56:31
+葛先生,13811638071,3027171803039749,VIP5,2025-12-28 21:38:25,1h 9m,小燕(1h52m),2025-12-28 22:48:42
+葛先生,13811638071,3027240911620101,VIP5,2025-12-28 22:48:44,0h 42m,小燕(0h42m),2025-12-28 23:32:00
+葛先生,13811638071,3027279097726917,A1,2025-12-28 23:23:12,0h 4m,,2025-12-29 00:45:50
+葛先生,13811638071,3027279097726917,C2,2025-12-28 23:27:34,1h 17m,婉婉(1h17m),2025-12-29 00:45:50
+葛先生,13811638071,3027283487705029,VIP5,2025-12-28 23:32:02,1h 38m,小燕(1h38m),2025-12-29 01:10:27
+葛先生,13811638071,3027381047756741,补时长7,2025-12-29 01:11:17,0h 0m,,2025-12-29 01:11:47
+葛先生,13811638071,3027494215747397,A1,2025-12-29 03:06:24,0h 0m,小燕(1h50m),2025-12-29 03:06:51
+葛先生,13811638071,3027520016877573,补时长5,2025-12-29 03:32:39,1h 40m,,2025-12-29 03:33:33
+葛先生,13811638071,3028365240272837,A6,2025-12-29 17:52:27,2h 3m,小燕(2h3m),2025-12-29 19:58:42
+葛先生,13811638071,3028488531724357,M5,2025-12-29 19:57:52,3h 3m,小燕(3h3m),2025-12-29 23:04:58
+葛先生,13811638071,3028489795159877,A6,2025-12-29 19:59:09,1h 2m,,2025-12-29 19:59:31
+葛先生,13811638071,3028620706809861,VIP5,2025-12-29 22:12:19,1h 2m,小柔(1h2m) 小燕(0h6m),2025-12-29 23:16:04
+葛先生,13811638071,3028672505759557,补时长7,2025-12-29 23:05:01,0h 0m,,2025-12-29 23:05:28
+葛先生,13811638071,3028796631942981,A1,2025-12-30 01:11:17,0h 0m,小燕(1h12m),2025-12-30 01:12:20
+葛先生,13811638071,3028797785933637,补时长6,2025-12-30 01:12:28,0h 0m,,2025-12-30 01:12:43
+葛先生,13811638071,3028798611277893,A6,2025-12-30 01:13:18,0h 51m,小燕(0h50m),2025-12-30 02:04:34
+葛先生,13811638071,3029823520163653,A6,2025-12-30 18:35:53,1h 30m,小燕(1h30m),2025-12-30 20:06:17
+葛先生,13811638071,3029912671930309,A2,2025-12-30 20:06:35,0h 45m,,2025-12-30 20:07:12
+葛先生,13811638071,3029920336283461,S1,2025-12-30 20:14:23,1h 9m,小燕(1h8m),2025-12-30 21:26:01
+葛先生,13811638071,3029953608239109,S3,2025-12-30 20:48:13,0h 54m,,2025-12-30 21:43:22
+葛先生,13811638071,3029990793086789,S1,2025-12-30 21:26:03,1h 22m,小燕(1h1m) 阿清(0h20m),2025-12-30 22:48:21
+葛先生,13811638071,3029991615416389,A6,2025-12-30 21:26:53,0h 50m,,2025-12-30 21:27:30
+葛先生,13811638071,3030051846162437,A6,2025-12-30 22:28:09,1h 35m,小燕(1h13m),2025-12-31 00:03:58
+葛先生,13811638071,3030071938451269,S1,2025-12-30 22:48:36,0h 45m,阿清(0h45m),2025-12-30 23:34:52
+葛先生,13811638071,3030329100781637,补时长2,2025-12-31 03:10:12,0h 1m,,2025-12-31 03:10:58
+葛先生,13811638071,3031047867485317,VIP1,2025-12-31 15:21:22,2h 15m,小燕(2h15m),2025-12-31 18:30:37
+葛先生,13811638071,3031246638532229,补时长2,2025-12-31 18:43:30,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3031246638532229,补时长3,2025-12-31 18:43:34,0h 0m,,2025-12-31 18:44:20
+葛先生,13811638071,3036870032656645,A6,2026-01-04 18:03:58,2h 15m,小燕(2h15m),2026-01-04 20:20:13
+葛先生,13811638071,3037004116691653,补时长7,2026-01-04 20:20:22,0h 0m,,2026-01-04 20:20:58
+葛先生,13811638071,3037130243574469,A7,2026-01-04 22:28:40,0h 0m,小燕(2h3m),2026-01-04 22:29:02
+葛先生,13811638071,3037131328588485,M5,2026-01-04 22:29:47,3h 9m,,2026-01-05 01:44:43
+葛先生,13811638071,3037318211751109,补时长7,2026-01-05 01:39:53,0h 0m,,2026-01-05 01:40:11
+葛先生,13811638071,3038663954582853,A6,2026-01-05 20:44:34,0h 21m,,2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,M5,2026-01-05 21:05:52,3h 0m,,2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,S1,2026-01-05 23:05:41,0h 57m,乔西(0h57m) 小燕(0h21m),2026-01-06 02:31:25
+葛先生,13811638071,3038597488594117,补时长7,2026-01-05 23:21:14,0h 0m,小燕(2h35m),2026-01-05 23:22:18
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:01,0h 0m,小燕(1h59m) 阿清(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:51,1h 59m,小燕(1h59m) 阿清(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3039616315803525,A1,2026-01-06 16:37:38,8h 50m,小燕(8h50m),2026-01-07 01:28:11
+葛先生,13811638071,3039824130983749,M7,2026-01-06 20:09:02,3h 22m,小燕(3h22m),2026-01-06 23:36:08
+葛先生,13811638071,3040027900495749,补时长7,2026-01-06 23:36:19,2h 0m,,2026-01-06 23:36:43
+葛先生,13811638071,3040128992692037,TV,2026-01-07 01:19:10,2h 46m,小燕(2h37m),2026-01-07 04:06:07
+葛先生,13811638071,3040137917564805,补时长7,2026-01-07 01:28:14,3h 0m,,2026-01-07 01:28:39
+葛先生,13811638071,3041502086645445,A6,2026-01-07 14:11:29,10h 24m,小燕(10h24m),2026-01-08 05:48:14
+葛先生,13811638071,3041240108402437,VIP5,2026-01-07 20:09:27,1h 11m,小燕(1h11m),2026-01-07 21:21:15
+葛先生,13811638071,3041310718166853,VIP5,2026-01-07 21:21:16,0h 46m,小燕(0h46m),2026-01-07 22:08:05
+葛先生,13811638071,3041356781012741,VIP5,2026-01-07 22:08:08,1h 2m,小燕(1h1m),2026-01-07 23:10:30
+葛先生,13811638071,3041418120349573,VIP5,2026-01-07 23:10:32,0h 49m,小燕(0h48m),2026-01-08 00:04:02
+葛先生,13811638071,3041502086645445,TV,2026-01-08 00:35:57,5h 11m,阿清(1h55m) 小燕(5h11m),2026-01-08 05:48:14
+葛先生,13811638071,3042589002975045,A6,2026-01-08 19:01:37,4h 9m,小燕(6h9m),2026-01-08 23:11:19
+葛先生,13811638071,3042699136239301,S1,2026-01-08 19:03:26,1h 50m,,2026-01-08 21:21:03
+葛先生,13811638071,3042699136239301,VIP5,2026-01-08 20:53:38,0h 27m,小燕(2h17m),2026-01-08 21:21:03
+葛先生,13811638071,3042796595971845,TV,2026-01-08 21:18:43,1h 13m,年糕(1h47m),2026-01-09 00:02:40
+葛先生,13811638071,3042726147917509,VIP5,2026-01-08 21:21:07,1h 22m,小燕(1h23m),2026-01-08 22:43:49
+葛先生,13811638071,3042796595971845,TV,2026-01-08 22:32:47,1h 28m,年糕(1h47m),2026-01-09 00:02:40
+葛先生,13811638071,3042589002975045,VIP5,2026-01-08 22:43:51,0h 26m,小燕(0h26m),2026-01-08 23:11:19
+葛先生,13811638071,3042835118278341,补时长7,2026-01-08 23:11:58,2h 0m,,2026-01-08 23:12:30
+葛先生,13811638071,3042885054465733,补时长7,2026-01-09 00:02:46,0h 0m,,2026-01-09 00:03:28
+葛先生,13811638071,3043910456903429,A6,2026-01-09 17:25:52,7h 34m,小燕(10h34m),2026-01-10 01:01:10
+葛先生,13811638071,3044081890182917,S2,2026-01-09 20:20:15,2h 15m,千千(2h13m),2026-01-09 22:38:08
+葛先生,13811638071,3044086761490309,666,2026-01-09 20:25:13,1h 54m,,2026-01-09 22:22:52
+葛先生,13811638071,3044105870411525,M7,2026-01-09 20:44:39,3h 49m,小燕(3h43m),2026-01-10 00:39:15
+葛先生,13811638071,3044358662178117,补时长6,2026-01-10 01:01:48,4h 0m,,2026-01-10 01:02:29
+葛先生,13811638071,3045217778599621,A6,2026-01-10 15:35:44,7h 33m,小燕(7h33m),2026-01-10 23:10:26
+葛先生,13811638071,3045663905318661,VIP5,2026-01-10 23:09:34,3h 7m,小燕(3h7m),2026-01-11 02:17:13
+葛先生,13811638071,3045763277047109,补时长5,2026-01-11 00:50:39,2h 2m,,2026-01-11 02:04:36
diff --git a/etl_billiards/reports/assistant_orders_13811638071_2026-01-01.csv b/etl_billiards/reports/assistant_orders_13811638071_2026-01-01.csv
new file mode 100644
index 0000000..16117a0
--- /dev/null
+++ b/etl_billiards/reports/assistant_orders_13811638071_2026-01-01.csv
@@ -0,0 +1,40 @@
+会员名称,会员手机号,订单号,桌台(房间)名称,开始时间,持续时间,助教挂钟信息,结账时间
+葛先生,13811638071,3036870032656645,A6,2026-01-04 18:03:58,2h 15m,小燕(2h15m),2026-01-04 20:20:13
+葛先生,13811638071,3037004116691653,补时长7,2026-01-04 20:20:22,0h 0m,,2026-01-04 20:20:58
+葛先生,13811638071,3037130243574469,A7,2026-01-04 22:28:40,0h 0m,小燕(2h3m),2026-01-04 22:29:02
+葛先生,13811638071,3037131328588485,M5,2026-01-04 22:29:47,3h 9m,,2026-01-05 01:44:43
+葛先生,13811638071,3037318211751109,补时长7,2026-01-05 01:39:53,0h 0m,,2026-01-05 01:40:11
+葛先生,13811638071,3038443483466437,A6,2026-01-05 20:44:34,0h 21m,,2026-01-06 02:31:25
+葛先生,13811638071,3038464422284485,M5,2026-01-05 21:05:52,3h 0m,,2026-01-06 02:31:25
+葛先生,13811638071,3038582201207493,S1,2026-01-05 23:05:41,0h 57m,乔西(0h57m) 小燕(0h21m),2026-01-06 02:31:25
+葛先生,13811638071,3038597488594117,补时长7,2026-01-05 23:21:14,0h 0m,小燕(2h35m),2026-01-05 23:22:18
+葛先生,13811638071,3038663145786693,TV,2026-01-06 00:28:01,0h 0m,阿清(1h59m) 小燕(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3038663954582853,TV,2026-01-06 00:28:51,1h 59m,阿清(1h59m) 小燕(1h59m),2026-01-06 02:31:25
+葛先生,13811638071,3039616315803525,A1,2026-01-06 16:37:38,8h 50m,小燕(8h50m),2026-01-07 01:28:11
+葛先生,13811638071,3039824130983749,M7,2026-01-06 20:09:02,3h 22m,小燕(3h22m),2026-01-06 23:36:08
+葛先生,13811638071,3040027900495749,补时长7,2026-01-06 23:36:19,2h 0m,,2026-01-06 23:36:43
+葛先生,13811638071,3040128992692037,TV,2026-01-07 01:19:10,2h 46m,小燕(2h37m),2026-01-07 04:06:07
+葛先生,13811638071,3040137917564805,补时长7,2026-01-07 01:28:14,3h 0m,,2026-01-07 01:28:39
+葛先生,13811638071,3040888209426117,A6,2026-01-07 14:11:29,10h 24m,小燕(10h24m),2026-01-08 05:48:14
+葛先生,13811638071,3041240108402437,VIP5,2026-01-07 20:09:27,1h 11m,小燕(1h11m),2026-01-07 21:21:15
+葛先生,13811638071,3041310718166853,VIP5,2026-01-07 21:21:16,0h 46m,小燕(0h46m) 小燕(0h0m),2026-01-07 22:08:05
+葛先生,13811638071,3041356781012741,VIP5,2026-01-07 22:08:08,1h 2m,小燕(1h1m),2026-01-07 23:10:30
+葛先生,13811638071,3041418120349573,VIP5,2026-01-07 23:10:32,0h 49m,小燕(0h48m),2026-01-08 00:04:02
+葛先生,13811638071,3041502086645445,TV,2026-01-08 00:35:57,5h 11m,阿清(1h55m) 小燕(5h11m),2026-01-08 05:48:14
+葛先生,13811638071,3042589002975045,A6,2026-01-08 19:01:37,4h 9m,小燕(0h0m) 小燕(4h9m) 小燕(0h0m),2026-01-08 23:11:19
+葛先生,13811638071,3042590786307781,S1,2026-01-08 19:03:26,1h 50m,小燕(0h0m),2026-01-08 21:21:03
+葛先生,13811638071,3042699136239301,VIP5,2026-01-08 20:53:38,0h 27m,小燕(2h17m),2026-01-08 21:21:03
+葛先生,13811638071,3042723784541957,TV,2026-01-08 21:18:43,1h 13m,年糕(1h28m) 年糕(0h0m) 年糕(0h19m),2026-01-09 00:02:40
+葛先生,13811638071,3042726147917509,VIP5,2026-01-08 21:21:07,1h 22m,小燕(1h23m),2026-01-08 22:43:49
+葛先生,13811638071,3042796595971845,TV,2026-01-08 22:32:47,1h 28m,年糕(1h28m) 年糕(0h0m) 年糕(0h19m),2026-01-09 00:02:40
+葛先生,13811638071,3042807473456837,VIP5,2026-01-08 22:43:51,0h 26m,小燕(0h26m),2026-01-08 23:11:19
+葛先生,13811638071,3042835118278341,补时长7,2026-01-08 23:11:58,2h 0m,,2026-01-08 23:12:30
+葛先生,13811638071,3042885054465733,补时长7,2026-01-09 00:02:46,0h 0m,,2026-01-09 00:03:28
+葛先生,13811638071,3043910456903429,A6,2026-01-09 17:25:52,7h 34m,小燕(7h34m) 小燕(0h0m) 小燕(0h0m),2026-01-10 01:01:10
+葛先生,13811638071,3044081890182917,S2,2026-01-09 20:20:15,2h 15m,千千(2h13m),2026-01-09 22:38:08
+葛先生,13811638071,3044086761490309,666,2026-01-09 20:25:13,1h 54m,,2026-01-09 22:22:52
+葛先生,13811638071,3044105870411525,M7,2026-01-09 20:44:39,3h 49m,小燕(0h0m) 小燕(3h43m),2026-01-10 00:39:15
+葛先生,13811638071,3044358662178117,补时长6,2026-01-10 01:01:48,4h 0m,,2026-01-10 01:02:29
+葛先生,13811638071,3045217778599621,A6,2026-01-10 15:35:44,7h 33m,小燕(7h33m) 小燕(0h0m),2026-01-10 23:10:26
+葛先生,13811638071,3045663905318661,VIP5,2026-01-10 23:09:34,3h 7m,小燕(3h7m),2026-01-11 02:17:13
+葛先生,13811638071,3045763277047109,补时长5,2026-01-11 00:50:39,2h 2m,,2026-01-11 02:04:36
diff --git a/etl_billiards/reports/assistant_overtime_rest_xiaoyan.csv b/etl_billiards/reports/assistant_overtime_rest_xiaoyan.csv
new file mode 100644
index 0000000..21a9db0
--- /dev/null
+++ b/etl_billiards/reports/assistant_overtime_rest_xiaoyan.csv
@@ -0,0 +1,3 @@
+助教昵称,桌台(房间)名称,超休课时,超休金额,超休原因,记录时间
+小燕,A6,小燕(0h0m),0,,2026-01-08 05:48:14
+小燕,VIP5,小燕(43h21m),99.70,,2026-01-08 22:43:49
diff --git a/etl_billiards/reports/data_integrity_history_20260119_045009.json b/etl_billiards/reports/data_integrity_history_20260119_045009.json
new file mode 100644
index 0000000..2256e1e
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260119_045009.json
@@ -0,0 +1,19596 @@
+{
+ "mode": "history",
+ "start": "2025-07-19T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-19T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-07-19T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 13,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1772,
+ "records_with_pk": 1772,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 351,
+ "records_with_pk": 351,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2489,
+ "records_with_pk": 2489,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1841,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 1841,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:29:02.969408+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 465,
+ "ods": 465,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 747,
+ "ods": 747,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 8,
+ "ods": 8,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465696
+ },
+ "generated_at": "2026-01-19T04:29:10.599938+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4602,
+ "records_with_pk": 4602,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 859,
+ "records_with_pk": 859,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 94,
+ "records_with_pk": 94,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5196,
+ "records_with_pk": 5196,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4763,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 4763,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:32:03.295726+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463355
+ },
+ "generated_at": "2026-01-19T04:32:10.696434+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3720,
+ "records_with_pk": 3720,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 19,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 654,
+ "records_with_pk": 654,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4816,
+ "records_with_pk": 4816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3810,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3810,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:34:51.620870+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 240,
+ "ods": 654,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 391.51,
+ "ods_sum": 781.44,
+ "diff": -389.93000000000006
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 69566.69,
+ "ods_sum": 192541.75,
+ "diff": -122975.06
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465264
+ },
+ "generated_at": "2026-01-19T04:34:59.669448+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1609,
+ "records_with_pk": 1609,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 283,
+ "records_with_pk": 283,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 23,
+ "records_with_pk": 23,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2158,
+ "records_with_pk": 2158,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1638,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 1638,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:37:23.852552+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464118
+ },
+ "generated_at": "2026-01-19T04:37:31.841246+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3874,
+ "records_with_pk": 3874,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 884,
+ "records_with_pk": 884,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5516,
+ "records_with_pk": 5516,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3999,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3999,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:40:12.032887+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463606
+ },
+ "generated_at": "2026-01-19T04:40:19.507626+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4011,
+ "records_with_pk": 4011,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 975,
+ "records_with_pk": 975,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5464,
+ "records_with_pk": 5464,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4118,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 4118,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:43:02.464682+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463463
+ },
+ "generated_at": "2026-01-19T04:43:09.833622+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 800,
+ "records_with_pk": 800,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 157,
+ "records_with_pk": 157,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 823,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 823,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:45:21.982028+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466243
+ },
+ "generated_at": "2026-01-19T04:45:29.561000+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 767,
+ "records_with_pk": 767,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 188,
+ "records_with_pk": 188,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1198,
+ "records_with_pk": 1198,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 790,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 790,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1594,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:47:42.751654+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466270
+ },
+ "generated_at": "2026-01-19T04:47:50.279193+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 531,
+ "records_with_pk": 531,
+ "missing": 403,
+ "missing_samples": [
+ {
+ "id": 3057020019230533
+ },
+ {
+ "id": 3057014990243589
+ },
+ {
+ "id": 3057013753005957
+ },
+ {
+ "id": 3057008518383429
+ },
+ {
+ "id": 3056995682600645
+ },
+ {
+ "id": 3056981741766533
+ },
+ {
+ "id": 3056979342640901
+ },
+ {
+ "id": 3056959684708101
+ },
+ {
+ "id": 3056956357510981
+ },
+ {
+ "id": 3056954936903557
+ },
+ {
+ "id": 3056953857476357
+ },
+ {
+ "id": 3056943938029253
+ },
+ {
+ "id": 3056938804184901
+ },
+ {
+ "id": 3056932651288325
+ },
+ {
+ "id": 3056931799222149
+ },
+ {
+ "id": 3056919515154117
+ },
+ {
+ "id": 3056914445453125
+ },
+ {
+ "id": 3056914261952325
+ },
+ {
+ "id": 3056910879508229
+ },
+ {
+ "id": 3056905331394245
+ },
+ {
+ "id": 3056902065473349
+ },
+ {
+ "id": 3056890892535685
+ },
+ {
+ "id": 3056890473858757
+ },
+ {
+ "id": 3056889854609285
+ },
+ {
+ "id": 3056888080123781
+ },
+ {
+ "id": 3056886248654661
+ },
+ {
+ "id": 3056884862027525
+ },
+ {
+ "id": 3056884219201413
+ },
+ {
+ "id": 3056883773802309
+ },
+ {
+ "id": 3056879992358597
+ },
+ {
+ "id": 3056877421627205
+ },
+ {
+ "id": 3056864070403973
+ },
+ {
+ "id": 3056854982575813
+ },
+ {
+ "id": 3056853929461637
+ },
+ {
+ "id": 3056853418247877
+ },
+ {
+ "id": 3056852563330885
+ },
+ {
+ "id": 3056850133452613
+ },
+ {
+ "id": 3056843048617797
+ },
+ {
+ "id": 3056837029676741
+ },
+ {
+ "id": 3056836306863877
+ },
+ {
+ "id": 3056826097174341
+ },
+ {
+ "id": 3056816570730181
+ },
+ {
+ "id": 3056811187324741
+ },
+ {
+ "id": 3056809281292165
+ },
+ {
+ "id": 3056808117716869
+ },
+ {
+ "id": 3056805507417925
+ },
+ {
+ "id": 3056796391950021
+ },
+ {
+ "id": 3056794821478149
+ },
+ {
+ "id": 3056794153469701
+ },
+ {
+ "id": 3056779331307270
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 114,
+ "records_with_pk": 114,
+ "missing": 74,
+ "missing_samples": [
+ {
+ "id": 3056982208005957
+ },
+ {
+ "id": 3056953997674373
+ },
+ {
+ "id": 3056953997002629
+ },
+ {
+ "id": 3056919597958981
+ },
+ {
+ "id": 3056911095482245
+ },
+ {
+ "id": 3056880172549957
+ },
+ {
+ "id": 3056880171992901
+ },
+ {
+ "id": 3056794939098949
+ },
+ {
+ "id": 3056794938640197
+ },
+ {
+ "id": 3056714097248069
+ },
+ {
+ "id": 3056525609060101
+ },
+ {
+ "id": 3055890048599813
+ },
+ {
+ "id": 3055890048124677
+ },
+ {
+ "id": 3055885302908613
+ },
+ {
+ "id": 3055854199539397
+ },
+ {
+ "id": 3055854199097029
+ },
+ {
+ "id": 3055763988301573
+ },
+ {
+ "id": 3055757794346693
+ },
+ {
+ "id": 3055757793871557
+ },
+ {
+ "id": 3055757793412805
+ },
+ {
+ "id": 3055757792888517
+ },
+ {
+ "id": 3055681672464197
+ },
+ {
+ "id": 3055639814948613
+ },
+ {
+ "id": 3055634623186757
+ },
+ {
+ "id": 3055634622744389
+ },
+ {
+ "id": 3055629233555269
+ },
+ {
+ "id": 3055598631093957
+ },
+ {
+ "id": 3055593876768518
+ },
+ {
+ "id": 3055540092061445
+ },
+ {
+ "id": 3055474913773253
+ },
+ {
+ "id": 3055298714142469
+ },
+ {
+ "id": 3055298713454341
+ },
+ {
+ "id": 3055298712979205
+ },
+ {
+ "id": 3055258938002821
+ },
+ {
+ "id": 3055258937462149
+ },
+ {
+ "id": 3055258936774021
+ },
+ {
+ "id": 3055177883585605
+ },
+ {
+ "id": 3055165426519365
+ },
+ {
+ "id": 3054532499983685
+ },
+ {
+ "id": 3054532499492165
+ },
+ {
+ "id": 3054369730432325
+ },
+ {
+ "id": 3054369729891653
+ },
+ {
+ "id": 3054369204112773
+ },
+ {
+ "id": 3054282272590917
+ },
+ {
+ "id": 3054276255534405
+ },
+ {
+ "id": 3054276255059269
+ },
+ {
+ "id": 3054270640983109
+ },
+ {
+ "id": 3054270333111621
+ },
+ {
+ "id": 3054270332259653
+ },
+ {
+ "id": 3054257700490309
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3055854198654661
+ },
+ {
+ "id": 3054102024031429
+ },
+ {
+ "id": 3054102024834245
+ },
+ {
+ "id": 3054102025833669
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11944,
+ "records_with_pk": 11944,
+ "missing": 440,
+ "missing_samples": [
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ },
+ {
+ "id": 3056884233275077
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 81,
+ "missing_samples": [
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ },
+ {
+ "id": 3054273873972613
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 13,
+ "records_with_pk": 13,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3055852804769541
+ },
+ {
+ "id": 3055757040240453
+ },
+ {
+ "id": 3055567463532421
+ },
+ {
+ "id": 3055177162837381
+ },
+ {
+ "id": 3054210385137029
+ },
+ {
+ "id": 3054195772001605
+ },
+ {
+ "id": 3053966621347013
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 688,
+ "records_with_pk": 688,
+ "missing": 496,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3057033942206213
+ },
+ {
+ "sitegoodsstockid": 3057020049737477
+ },
+ {
+ "sitegoodsstockid": 3057014058862405
+ },
+ {
+ "sitegoodsstockid": 3057009674340165
+ },
+ {
+ "sitegoodsstockid": 3057005598492421
+ },
+ {
+ "sitegoodsstockid": 3057004882659141
+ },
+ {
+ "sitegoodsstockid": 3056997868406661
+ },
+ {
+ "sitegoodsstockid": 3056979367380805
+ },
+ {
+ "sitegoodsstockid": 3056967704184645
+ },
+ {
+ "sitegoodsstockid": 3056961133971333
+ },
+ {
+ "sitegoodsstockid": 3056949671331589
+ },
+ {
+ "sitegoodsstockid": 3056911529903941
+ },
+ {
+ "sitegoodsstockid": 3056911312242565
+ },
+ {
+ "sitegoodsstockid": 3056910612252485
+ },
+ {
+ "sitegoodsstockid": 3056910612776773
+ },
+ {
+ "sitegoodsstockid": 3056910613432133
+ },
+ {
+ "sitegoodsstockid": 3056890725517061
+ },
+ {
+ "sitegoodsstockid": 3056888105731845
+ },
+ {
+ "sitegoodsstockid": 3056888105895685
+ },
+ {
+ "sitegoodsstockid": 3056887950313349
+ },
+ {
+ "sitegoodsstockid": 3056884951287685
+ },
+ {
+ "sitegoodsstockid": 3056881394812805
+ },
+ {
+ "sitegoodsstockid": 3056868923803461
+ },
+ {
+ "sitegoodsstockid": 3056867086780165
+ },
+ {
+ "sitegoodsstockid": 3056867087369989
+ },
+ {
+ "sitegoodsstockid": 3056867086010117
+ },
+ {
+ "sitegoodsstockid": 3056866232600261
+ },
+ {
+ "sitegoodsstockid": 3056850159027973
+ },
+ {
+ "sitegoodsstockid": 3056847869511429
+ },
+ {
+ "sitegoodsstockid": 3056847870068485
+ },
+ {
+ "sitegoodsstockid": 3056837533452037
+ },
+ {
+ "sitegoodsstockid": 3056837532845829
+ },
+ {
+ "sitegoodsstockid": 3056811220617093
+ },
+ {
+ "sitegoodsstockid": 3056811220453253
+ },
+ {
+ "sitegoodsstockid": 3056808611137349
+ },
+ {
+ "sitegoodsstockid": 3056805312218885
+ },
+ {
+ "sitegoodsstockid": 3056805313136389
+ },
+ {
+ "sitegoodsstockid": 3056805312694021
+ },
+ {
+ "sitegoodsstockid": 3056804676077445
+ },
+ {
+ "sitegoodsstockid": 3056804675569541
+ },
+ {
+ "sitegoodsstockid": 3056797925508869
+ },
+ {
+ "sitegoodsstockid": 3056797925984005
+ },
+ {
+ "sitegoodsstockid": 3056797925017349
+ },
+ {
+ "sitegoodsstockid": 3056796414658245
+ },
+ {
+ "sitegoodsstockid": 3056796414822085
+ },
+ {
+ "sitegoodsstockid": 3056794178750341
+ },
+ {
+ "sitegoodsstockid": 3056794002392837
+ },
+ {
+ "sitegoodsstockid": 3056776751368005
+ },
+ {
+ "sitegoodsstockid": 3056753449502597
+ },
+ {
+ "sitegoodsstockid": 3056753449994117
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 554,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 554,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 2578,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:50:01.850743+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 120,
+ "diff": -120
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 120,
+ "ods": 120,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 3910.16,
+ "ods_sum": 3910.16,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17482.25,
+ "ods_sum": 17482.25,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1857.77,
+ "ods_sum": 1857.77,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 9785.64,
+ "ods_sum": 9785.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14270.54,
+ "ods_sum": 14270.54,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 87,
+ "ods": 87,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4940.0,
+ "ods_sum": 4940.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4584.0,
+ "ods_sum": 4584.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 136,
+ "ods": 136,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 32589.0,
+ "ods_sum": 32589.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466822
+ },
+ "generated_at": "2026-01-19T04:50:09.580038+08:00"
+ }
+ ],
+ "total_missing": 15330,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T04:50:09.580069+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260119_060453.json b/etl_billiards/reports/data_integrity_history_20260119_060453.json
new file mode 100644
index 0000000..5d0d878
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260119_060453.json
@@ -0,0 +1,45066 @@
+{
+ "mode": "history",
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2026-01-20T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "label": "month_2024-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 13,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:16:03.413933+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:16:10.340880+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "label": "month_2024-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:18:18.859264+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:18:25.963176+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "label": "month_2024-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:20:35.610517+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:20:43.003907+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "label": "month_2024-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:22:53.103666+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:22:59.984747+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "label": "month_2024-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:25:11.189695+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:25:18.239968+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "label": "month_2024-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:27:27.161324+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:27:34.687853+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "label": "month_2025-01-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:29:46.816466+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:29:53.812921+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "label": "month_2025-02-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 28,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:32:06.622181+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:32:13.586062+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "label": "month_2025-03-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:34:23.320570+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:34:30.520324+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "label": "month_2025-04-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:36:41.568189+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:36:48.946053+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "label": "month_2025-05-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:38:56.912079+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:39:04.047468+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "label": "month_2025-06-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:41:13.649791+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T05:41:20.915372+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1776,
+ "records_with_pk": 1776,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 351,
+ "records_with_pk": 351,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2551,
+ "records_with_pk": 2551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1845,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 1845,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:43:45.422258+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465696
+ },
+ "generated_at": "2026-01-19T05:43:52.416481+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4602,
+ "records_with_pk": 4602,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 859,
+ "records_with_pk": 859,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 94,
+ "records_with_pk": 94,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5196,
+ "records_with_pk": 5196,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4763,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 4763,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:46:36.578682+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463355
+ },
+ "generated_at": "2026-01-19T05:46:43.457148+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3720,
+ "records_with_pk": 3720,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 19,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 654,
+ "records_with_pk": 654,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4816,
+ "records_with_pk": 4816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3810,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3810,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:49:26.890701+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 240,
+ "ods": 654,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 391.51,
+ "ods_sum": 781.44,
+ "diff": -389.93000000000006
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 69566.69,
+ "ods_sum": 192541.75,
+ "diff": -122975.06
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465264
+ },
+ "generated_at": "2026-01-19T05:49:33.556140+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1609,
+ "records_with_pk": 1609,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 283,
+ "records_with_pk": 283,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 23,
+ "records_with_pk": 23,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2158,
+ "records_with_pk": 2158,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1638,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 1638,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:51:57.549176+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464118
+ },
+ "generated_at": "2026-01-19T05:52:04.976535+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3874,
+ "records_with_pk": 3874,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 884,
+ "records_with_pk": 884,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5516,
+ "records_with_pk": 5516,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3999,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3999,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:54:46.471379+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463606
+ },
+ "generated_at": "2026-01-19T05:54:53.951338+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4011,
+ "records_with_pk": 4011,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 975,
+ "records_with_pk": 975,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5464,
+ "records_with_pk": 5464,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4118,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 4118,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:57:40.216434+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463463
+ },
+ "generated_at": "2026-01-19T05:57:46.966076+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 800,
+ "records_with_pk": 800,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 157,
+ "records_with_pk": 157,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 823,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 823,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T05:59:57.867109+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466243
+ },
+ "generated_at": "2026-01-19T06:00:05.211141+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 767,
+ "records_with_pk": 767,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 188,
+ "records_with_pk": 188,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1198,
+ "records_with_pk": 1198,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 790,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 790,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:02:22.012058+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466270
+ },
+ "generated_at": "2026-01-19T06:02:29.217420+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-20T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-20T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 424,
+ "missing_samples": [
+ {
+ "id": 3057290422912837
+ },
+ {
+ "id": 3057269702969221
+ },
+ {
+ "id": 3057249723926405
+ },
+ {
+ "id": 3057219761817285
+ },
+ {
+ "id": 3057214065969029
+ },
+ {
+ "id": 3057209908758213
+ },
+ {
+ "id": 3057206570534725
+ },
+ {
+ "id": 3057196624627525
+ },
+ {
+ "id": 3057177203099397
+ },
+ {
+ "id": 3057166977042245
+ },
+ {
+ "id": 3057156407166661
+ },
+ {
+ "id": 3057134753875781
+ },
+ {
+ "id": 3057078852978373
+ },
+ {
+ "id": 3057073780868805
+ },
+ {
+ "id": 3057069481494341
+ },
+ {
+ "id": 3057068241651525
+ },
+ {
+ "id": 3057055047960453
+ },
+ {
+ "id": 3057052431304581
+ },
+ {
+ "id": 3057048509925061
+ },
+ {
+ "id": 3057046131721989
+ },
+ {
+ "id": 3057043840960261
+ },
+ {
+ "id": 3057020019230533
+ },
+ {
+ "id": 3057014990243589
+ },
+ {
+ "id": 3057013753005957
+ },
+ {
+ "id": 3057008518383429
+ },
+ {
+ "id": 3056995682600645
+ },
+ {
+ "id": 3056981741766533
+ },
+ {
+ "id": 3056979342640901
+ },
+ {
+ "id": 3056959684708101
+ },
+ {
+ "id": 3056956357510981
+ },
+ {
+ "id": 3056954936903557
+ },
+ {
+ "id": 3056953857476357
+ },
+ {
+ "id": 3056943938029253
+ },
+ {
+ "id": 3056938804184901
+ },
+ {
+ "id": 3056932651288325
+ },
+ {
+ "id": 3056931799222149
+ },
+ {
+ "id": 3056919515154117
+ },
+ {
+ "id": 3056914445453125
+ },
+ {
+ "id": 3056914261952325
+ },
+ {
+ "id": 3056910879508229
+ },
+ {
+ "id": 3056905331394245
+ },
+ {
+ "id": 3056902065473349
+ },
+ {
+ "id": 3056890892535685
+ },
+ {
+ "id": 3056890473858757
+ },
+ {
+ "id": 3056889854609285
+ },
+ {
+ "id": 3056888080123781
+ },
+ {
+ "id": 3056886248654661
+ },
+ {
+ "id": 3056884862027525
+ },
+ {
+ "id": 3056884219201413
+ },
+ {
+ "id": 3056883773802309
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 119,
+ "records_with_pk": 119,
+ "missing": 79,
+ "missing_samples": [
+ {
+ "id": 3057214127572805
+ },
+ {
+ "id": 3057214127146821
+ },
+ {
+ "id": 3057210214008517
+ },
+ {
+ "id": 3057167231715077
+ },
+ {
+ "id": 3057068424185541
+ },
+ {
+ "id": 3056982208005957
+ },
+ {
+ "id": 3056953997674373
+ },
+ {
+ "id": 3056953997002629
+ },
+ {
+ "id": 3056919597958981
+ },
+ {
+ "id": 3056911095482245
+ },
+ {
+ "id": 3056880172549957
+ },
+ {
+ "id": 3056880171992901
+ },
+ {
+ "id": 3056794939098949
+ },
+ {
+ "id": 3056794938640197
+ },
+ {
+ "id": 3056714097248069
+ },
+ {
+ "id": 3056525609060101
+ },
+ {
+ "id": 3055890048599813
+ },
+ {
+ "id": 3055890048124677
+ },
+ {
+ "id": 3055885302908613
+ },
+ {
+ "id": 3055854199539397
+ },
+ {
+ "id": 3055854199097029
+ },
+ {
+ "id": 3055763988301573
+ },
+ {
+ "id": 3055757794346693
+ },
+ {
+ "id": 3055757793871557
+ },
+ {
+ "id": 3055757793412805
+ },
+ {
+ "id": 3055757792888517
+ },
+ {
+ "id": 3055681672464197
+ },
+ {
+ "id": 3055639814948613
+ },
+ {
+ "id": 3055634623186757
+ },
+ {
+ "id": 3055634622744389
+ },
+ {
+ "id": 3055629233555269
+ },
+ {
+ "id": 3055598631093957
+ },
+ {
+ "id": 3055593876768518
+ },
+ {
+ "id": 3055540092061445
+ },
+ {
+ "id": 3055474913773253
+ },
+ {
+ "id": 3055298714142469
+ },
+ {
+ "id": 3055298713454341
+ },
+ {
+ "id": 3055298712979205
+ },
+ {
+ "id": 3055258938002821
+ },
+ {
+ "id": 3055258937462149
+ },
+ {
+ "id": 3055258936774021
+ },
+ {
+ "id": 3055177883585605
+ },
+ {
+ "id": 3055165426519365
+ },
+ {
+ "id": 3054532499983685
+ },
+ {
+ "id": 3054532499492165
+ },
+ {
+ "id": 3054369730432325
+ },
+ {
+ "id": 3054369729891653
+ },
+ {
+ "id": 3054369204112773
+ },
+ {
+ "id": 3054282272590917
+ },
+ {
+ "id": 3054276255534405
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3055854198654661
+ },
+ {
+ "id": 3054102024031429
+ },
+ {
+ "id": 3054102024834245
+ },
+ {
+ "id": 3054102025833669
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3057333865711429
+ },
+ {
+ "id": 3057069833078469
+ },
+ {
+ "id": 3055852804769541
+ },
+ {
+ "id": 3055757040240453
+ },
+ {
+ "id": 3055567463532421
+ },
+ {
+ "id": 3055177162837381
+ },
+ {
+ "id": 3054210385137029
+ },
+ {
+ "id": 3054195772001605
+ },
+ {
+ "id": 3053966621347013
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 718,
+ "records_with_pk": 718,
+ "missing": 526,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3057376085329669
+ },
+ {
+ "sitegoodsstockid": 3057370028885765
+ },
+ {
+ "sitegoodsstockid": 3057367488546629
+ },
+ {
+ "sitegoodsstockid": 3057334818457349
+ },
+ {
+ "sitegoodsstockid": 3057283158640389
+ },
+ {
+ "sitegoodsstockid": 3057283159115525
+ },
+ {
+ "sitegoodsstockid": 3057249985480517
+ },
+ {
+ "sitegoodsstockid": 3057238611035909
+ },
+ {
+ "sitegoodsstockid": 3057214401595269
+ },
+ {
+ "sitegoodsstockid": 3057193758230341
+ },
+ {
+ "sitegoodsstockid": 3057193758721861
+ },
+ {
+ "sitegoodsstockid": 3057193757755205
+ },
+ {
+ "sitegoodsstockid": 3057191498975045
+ },
+ {
+ "sitegoodsstockid": 3057191498467141
+ },
+ {
+ "sitegoodsstockid": 3057177227003717
+ },
+ {
+ "sitegoodsstockid": 3057167387543237
+ },
+ {
+ "sitegoodsstockid": 3057125713381253
+ },
+ {
+ "sitegoodsstockid": 3057105202415493
+ },
+ {
+ "sitegoodsstockid": 3057095130416837
+ },
+ {
+ "sitegoodsstockid": 3057092912613125
+ },
+ {
+ "sitegoodsstockid": 3057092912137989
+ },
+ {
+ "sitegoodsstockid": 3057085770663685
+ },
+ {
+ "sitegoodsstockid": 3057084025046917
+ },
+ {
+ "sitegoodsstockid": 3057084025505669
+ },
+ {
+ "sitegoodsstockid": 3057073805133701
+ },
+ {
+ "sitegoodsstockid": 3057073804969861
+ },
+ {
+ "sitegoodsstockid": 3057070111688389
+ },
+ {
+ "sitegoodsstockid": 3057070112229061
+ },
+ {
+ "sitegoodsstockid": 3057066868950725
+ },
+ {
+ "sitegoodsstockid": 3057065029289733
+ },
+ {
+ "sitegoodsstockid": 3057033942206213
+ },
+ {
+ "sitegoodsstockid": 3057020049737477
+ },
+ {
+ "sitegoodsstockid": 3057014058862405
+ },
+ {
+ "sitegoodsstockid": 3057009674340165
+ },
+ {
+ "sitegoodsstockid": 3057005598492421
+ },
+ {
+ "sitegoodsstockid": 3057004882659141
+ },
+ {
+ "sitegoodsstockid": 3056997868406661
+ },
+ {
+ "sitegoodsstockid": 3056979367380805
+ },
+ {
+ "sitegoodsstockid": 3056967704184645
+ },
+ {
+ "sitegoodsstockid": 3056961133971333
+ },
+ {
+ "sitegoodsstockid": 3056949671331589
+ },
+ {
+ "sitegoodsstockid": 3056911529903941
+ },
+ {
+ "sitegoodsstockid": 3056911312242565
+ },
+ {
+ "sitegoodsstockid": 3056910612252485
+ },
+ {
+ "sitegoodsstockid": 3056910612776773
+ },
+ {
+ "sitegoodsstockid": 3056910613432133
+ },
+ {
+ "sitegoodsstockid": 3056890725517061
+ },
+ {
+ "sitegoodsstockid": 3056888105731845
+ },
+ {
+ "sitegoodsstockid": 3056888105895685
+ },
+ {
+ "sitegoodsstockid": 3056887950313349
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 577,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 577,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 2638,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:04:45.914825+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 120,
+ "diff": -120
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 120,
+ "ods": 120,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 3910.16,
+ "ods_sum": 3910.16,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17482.25,
+ "ods_sum": 17482.25,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1857.77,
+ "ods_sum": 1857.77,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 9785.64,
+ "ods_sum": 9785.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14270.54,
+ "ods_sum": 14270.54,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 87,
+ "ods": 87,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4940.0,
+ "ods_sum": 4940.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4584.0,
+ "ods_sum": 4584.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 136,
+ "ods": 136,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 32589.0,
+ "ods_sum": 32589.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466822
+ },
+ "generated_at": "2026-01-19T06:04:53.436363+08:00"
+ }
+ ],
+ "total_missing": 34558,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:04:53.436384+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260119_070903.json b/etl_billiards/reports/data_integrity_history_20260119_070903.json
new file mode 100644
index 0000000..8220dc8
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260119_070903.json
@@ -0,0 +1,45060 @@
+{
+ "mode": "history",
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "label": "month_2024-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 13,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:20:16.187738+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:20:22.688674+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "label": "month_2024-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:22:37.815124+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:22:43.923006+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "label": "month_2024-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:24:56.215004+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:25:02.592886+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "label": "month_2024-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1672,
+ "records_with_pk": 1672,
+ "missing": 54,
+ "missing_samples": [
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ },
+ {
+ "id": 3054138081529221
+ },
+ {
+ "id": 3054115905686917
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1596,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:27:13.308390+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:27:19.824089+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "label": "month_2024-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 372,
+ "missing_samples": [
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ },
+ {
+ "id": 3056864356124421
+ },
+ {
+ "id": 3056855001057029
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11945,
+ "records_with_pk": 11945,
+ "missing": 441,
+ "missing_samples": [
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ },
+ {
+ "id": 3056884949387141
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 82,
+ "missing_samples": [
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ },
+ {
+ "id": 3054276249718085
+ },
+ {
+ "id": 3054276249505093
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1598,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:29:34.593009+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:29:40.636427+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "label": "month_2024-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:31:53.827843+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:32:00.367254+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "label": "month_2025-01-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:34:13.749930+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:34:20.005181+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "label": "month_2025-02-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 28,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:36:31.765924+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:36:38.138899+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "label": "month_2025-03-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:38:48.030981+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:38:54.341440+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "label": "month_2025-04-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:41:05.184192+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:41:11.517615+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "label": "month_2025-05-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:43:21.997877+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:43:28.282372+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "label": "month_2025-06-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:45:39.004065+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466942
+ },
+ "generated_at": "2026-01-19T06:45:45.722301+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1776,
+ "records_with_pk": 1776,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 351,
+ "records_with_pk": 351,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2551,
+ "records_with_pk": 2551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1845,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 1845,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:48:11.526513+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465696
+ },
+ "generated_at": "2026-01-19T06:48:18.040769+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4602,
+ "records_with_pk": 4602,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 859,
+ "records_with_pk": 859,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 94,
+ "records_with_pk": 94,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5196,
+ "records_with_pk": 5196,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4763,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 4763,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:51:02.036133+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463355
+ },
+ "generated_at": "2026-01-19T06:51:08.367639+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3720,
+ "records_with_pk": 3720,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 19,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 654,
+ "records_with_pk": 654,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4816,
+ "records_with_pk": 4816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3810,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3810,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:53:43.429411+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 240,
+ "ods": 654,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 391.51,
+ "ods_sum": 781.44,
+ "diff": -389.93000000000006
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 69566.69,
+ "ods_sum": 192541.75,
+ "diff": -122975.06
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 465264
+ },
+ "generated_at": "2026-01-19T06:53:50.113258+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1609,
+ "records_with_pk": 1609,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 283,
+ "records_with_pk": 283,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 23,
+ "records_with_pk": 23,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2158,
+ "records_with_pk": 2158,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1638,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 1638,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:56:13.928307+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464118
+ },
+ "generated_at": "2026-01-19T06:56:20.356765+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3874,
+ "records_with_pk": 3874,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 884,
+ "records_with_pk": 884,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5516,
+ "records_with_pk": 5516,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3999,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3999,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T06:59:03.053434+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463606
+ },
+ "generated_at": "2026-01-19T06:59:09.457245+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4011,
+ "records_with_pk": 4011,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 975,
+ "records_with_pk": 975,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5464,
+ "records_with_pk": 5464,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4118,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 4118,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:01:56.029438+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463463
+ },
+ "generated_at": "2026-01-19T07:02:02.613868+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 800,
+ "records_with_pk": 800,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 157,
+ "records_with_pk": 157,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 823,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 823,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:04:16.514521+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466243
+ },
+ "generated_at": "2026-01-19T07:04:23.505955+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 767,
+ "records_with_pk": 767,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 188,
+ "records_with_pk": 188,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1198,
+ "records_with_pk": 1198,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 790,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 790,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1603,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:06:38.684815+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466270
+ },
+ "generated_at": "2026-01-19T07:06:45.078231+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3056644876634181
+ },
+ {
+ "id": 3053833422211141
+ },
+ {
+ "id": 3053834039789701
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 531,
+ "records_with_pk": 531,
+ "missing": 403,
+ "missing_samples": [
+ {
+ "id": 3057020019230533
+ },
+ {
+ "id": 3057014990243589
+ },
+ {
+ "id": 3057013753005957
+ },
+ {
+ "id": 3057008518383429
+ },
+ {
+ "id": 3056995682600645
+ },
+ {
+ "id": 3056981741766533
+ },
+ {
+ "id": 3056979342640901
+ },
+ {
+ "id": 3056959684708101
+ },
+ {
+ "id": 3056956357510981
+ },
+ {
+ "id": 3056954936903557
+ },
+ {
+ "id": 3056953857476357
+ },
+ {
+ "id": 3056943938029253
+ },
+ {
+ "id": 3056938804184901
+ },
+ {
+ "id": 3056932651288325
+ },
+ {
+ "id": 3056931799222149
+ },
+ {
+ "id": 3056919515154117
+ },
+ {
+ "id": 3056914445453125
+ },
+ {
+ "id": 3056914261952325
+ },
+ {
+ "id": 3056910879508229
+ },
+ {
+ "id": 3056905331394245
+ },
+ {
+ "id": 3056902065473349
+ },
+ {
+ "id": 3056890892535685
+ },
+ {
+ "id": 3056890473858757
+ },
+ {
+ "id": 3056889854609285
+ },
+ {
+ "id": 3056888080123781
+ },
+ {
+ "id": 3056886248654661
+ },
+ {
+ "id": 3056884862027525
+ },
+ {
+ "id": 3056884219201413
+ },
+ {
+ "id": 3056883773802309
+ },
+ {
+ "id": 3056879992358597
+ },
+ {
+ "id": 3056877421627205
+ },
+ {
+ "id": 3056864070403973
+ },
+ {
+ "id": 3056854982575813
+ },
+ {
+ "id": 3056853929461637
+ },
+ {
+ "id": 3056853418247877
+ },
+ {
+ "id": 3056852563330885
+ },
+ {
+ "id": 3056850133452613
+ },
+ {
+ "id": 3056843048617797
+ },
+ {
+ "id": 3056837029676741
+ },
+ {
+ "id": 3056836306863877
+ },
+ {
+ "id": 3056826097174341
+ },
+ {
+ "id": 3056816570730181
+ },
+ {
+ "id": 3056811187324741
+ },
+ {
+ "id": 3056809281292165
+ },
+ {
+ "id": 3056808117716869
+ },
+ {
+ "id": 3056805507417925
+ },
+ {
+ "id": 3056796391950021
+ },
+ {
+ "id": 3056794821478149
+ },
+ {
+ "id": 3056794153469701
+ },
+ {
+ "id": 3056779331307270
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 374,
+ "missing_samples": [
+ {
+ "id": 3057420699731781
+ },
+ {
+ "id": 3057420699715397
+ },
+ {
+ "id": 3057290455943045
+ },
+ {
+ "id": 3057270101657477
+ },
+ {
+ "id": 3057220482795333
+ },
+ {
+ "id": 3057214126622533
+ },
+ {
+ "id": 3057214126606149
+ },
+ {
+ "id": 3057210213598917
+ },
+ {
+ "id": 3057206587131781
+ },
+ {
+ "id": 3057196644271877
+ },
+ {
+ "id": 3057167231223557
+ },
+ {
+ "id": 3057156450273157
+ },
+ {
+ "id": 3057134773798789
+ },
+ {
+ "id": 3057078869640965
+ },
+ {
+ "id": 3057069562889925
+ },
+ {
+ "id": 3057069562906309
+ },
+ {
+ "id": 3057068423825093
+ },
+ {
+ "id": 3057055305549573
+ },
+ {
+ "id": 3057052574369477
+ },
+ {
+ "id": 3057048527652741
+ },
+ {
+ "id": 3057046180382533
+ },
+ {
+ "id": 3057043856557893
+ },
+ {
+ "id": 3057015007364933
+ },
+ {
+ "id": 3057013774141253
+ },
+ {
+ "id": 3057008534603589
+ },
+ {
+ "id": 3056995705063237
+ },
+ {
+ "id": 3056959701501702
+ },
+ {
+ "id": 3056956401584005
+ },
+ {
+ "id": 3056954953582277
+ },
+ {
+ "id": 3056953996527493
+ },
+ {
+ "id": 3056953996494725
+ },
+ {
+ "id": 3056943960491845
+ },
+ {
+ "id": 3056938839656133
+ },
+ {
+ "id": 3056932669343557
+ },
+ {
+ "id": 3056931819980485
+ },
+ {
+ "id": 3056919597270853
+ },
+ {
+ "id": 3056914461148869
+ },
+ {
+ "id": 3056914282186437
+ },
+ {
+ "id": 3056911094941573
+ },
+ {
+ "id": 3056905346926341
+ },
+ {
+ "id": 3056902089623301
+ },
+ {
+ "id": 3056891125925765
+ },
+ {
+ "id": 3056890529072965
+ },
+ {
+ "id": 3056889939511045
+ },
+ {
+ "id": 3056886265759493
+ },
+ {
+ "id": 3056884235601605
+ },
+ {
+ "id": 3056884026673029
+ },
+ {
+ "id": 3056880171370309
+ },
+ {
+ "id": 3056880171403077
+ },
+ {
+ "id": 3056877437257605
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 114,
+ "records_with_pk": 114,
+ "missing": 74,
+ "missing_samples": [
+ {
+ "id": 3056982208005957
+ },
+ {
+ "id": 3056953997674373
+ },
+ {
+ "id": 3056953997002629
+ },
+ {
+ "id": 3056919597958981
+ },
+ {
+ "id": 3056911095482245
+ },
+ {
+ "id": 3056880172549957
+ },
+ {
+ "id": 3056880171992901
+ },
+ {
+ "id": 3056794939098949
+ },
+ {
+ "id": 3056794938640197
+ },
+ {
+ "id": 3056714097248069
+ },
+ {
+ "id": 3056525609060101
+ },
+ {
+ "id": 3055890048599813
+ },
+ {
+ "id": 3055890048124677
+ },
+ {
+ "id": 3055885302908613
+ },
+ {
+ "id": 3055854199539397
+ },
+ {
+ "id": 3055854199097029
+ },
+ {
+ "id": 3055763988301573
+ },
+ {
+ "id": 3055757794346693
+ },
+ {
+ "id": 3055757793871557
+ },
+ {
+ "id": 3055757793412805
+ },
+ {
+ "id": 3055757792888517
+ },
+ {
+ "id": 3055681672464197
+ },
+ {
+ "id": 3055639814948613
+ },
+ {
+ "id": 3055634623186757
+ },
+ {
+ "id": 3055634622744389
+ },
+ {
+ "id": 3055629233555269
+ },
+ {
+ "id": 3055598631093957
+ },
+ {
+ "id": 3055593876768518
+ },
+ {
+ "id": 3055540092061445
+ },
+ {
+ "id": 3055474913773253
+ },
+ {
+ "id": 3055298714142469
+ },
+ {
+ "id": 3055298713454341
+ },
+ {
+ "id": 3055298712979205
+ },
+ {
+ "id": 3055258938002821
+ },
+ {
+ "id": 3055258937462149
+ },
+ {
+ "id": 3055258936774021
+ },
+ {
+ "id": 3055177883585605
+ },
+ {
+ "id": 3055165426519365
+ },
+ {
+ "id": 3054532499983685
+ },
+ {
+ "id": 3054532499492165
+ },
+ {
+ "id": 3054369730432325
+ },
+ {
+ "id": 3054369729891653
+ },
+ {
+ "id": 3054369204112773
+ },
+ {
+ "id": 3054282272590917
+ },
+ {
+ "id": 3054276255534405
+ },
+ {
+ "id": 3054276255059269
+ },
+ {
+ "id": 3054270640983109
+ },
+ {
+ "id": 3054270333111621
+ },
+ {
+ "id": 3054270332259653
+ },
+ {
+ "id": 3054257700490309
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3055854198654661
+ },
+ {
+ "id": 3054102024031429
+ },
+ {
+ "id": 3054102024834245
+ },
+ {
+ "id": 3054102025833669
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 442,
+ "missing_samples": [
+ {
+ "id": 3057420694800197
+ },
+ {
+ "id": 3057333867546437
+ },
+ {
+ "id": 3057290453387141
+ },
+ {
+ "id": 3057270099101573
+ },
+ {
+ "id": 3057249983973189
+ },
+ {
+ "id": 3057220480157509
+ },
+ {
+ "id": 3057214122526533
+ },
+ {
+ "id": 3057210211583685
+ },
+ {
+ "id": 3057206584838021
+ },
+ {
+ "id": 3057196642354949
+ },
+ {
+ "id": 3057177225267013
+ },
+ {
+ "id": 3057167228438277
+ },
+ {
+ "id": 3057156447733637
+ },
+ {
+ "id": 3057134771554181
+ },
+ {
+ "id": 3057078867642117
+ },
+ {
+ "id": 3057073803233157
+ },
+ {
+ "id": 3057069834880709
+ },
+ {
+ "id": 3057069558793925
+ },
+ {
+ "id": 3057068420794053
+ },
+ {
+ "id": 3057055303141125
+ },
+ {
+ "id": 3057052571993797
+ },
+ {
+ "id": 3057048525129605
+ },
+ {
+ "id": 3057046177646405
+ },
+ {
+ "id": 3057043854395205
+ },
+ {
+ "id": 3057020047984389
+ },
+ {
+ "id": 3057015004841797
+ },
+ {
+ "id": 3057013771847493
+ },
+ {
+ "id": 3057008531998533
+ },
+ {
+ "id": 3056995699345221
+ },
+ {
+ "id": 3056982205040453
+ },
+ {
+ "id": 3056979365758789
+ },
+ {
+ "id": 3056959699109637
+ },
+ {
+ "id": 3056956398634885
+ },
+ {
+ "id": 3056954950829765
+ },
+ {
+ "id": 3056953992595333
+ },
+ {
+ "id": 3056943958017861
+ },
+ {
+ "id": 3056938836772549
+ },
+ {
+ "id": 3056932666804038
+ },
+ {
+ "id": 3056931816556229
+ },
+ {
+ "id": 3056919593535301
+ },
+ {
+ "id": 3056914458920645
+ },
+ {
+ "id": 3056914279007941
+ },
+ {
+ "id": 3056911091976069
+ },
+ {
+ "id": 3056905343977221
+ },
+ {
+ "id": 3056902087231237
+ },
+ {
+ "id": 3056891123484549
+ },
+ {
+ "id": 3056890525697861
+ },
+ {
+ "id": 3056889936201477
+ },
+ {
+ "id": 3056888103896837
+ },
+ {
+ "id": 3056886263170821
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053789949006597
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 317,
+ "missing_samples": [
+ {
+ "id": 3057136826615493
+ },
+ {
+ "id": 3057082985907909
+ },
+ {
+ "id": 3057027593995973
+ },
+ {
+ "id": 3057019665631109
+ },
+ {
+ "id": 3057016039475077
+ },
+ {
+ "id": 3056989023389381
+ },
+ {
+ "id": 3056984840111813
+ },
+ {
+ "id": 3056956100855557
+ },
+ {
+ "id": 3056954554402693
+ },
+ {
+ "id": 3056949075396485
+ },
+ {
+ "id": 3056936359184261
+ },
+ {
+ "id": 3056908010424197
+ },
+ {
+ "id": 3056895507990277
+ },
+ {
+ "id": 3056882786387653
+ },
+ {
+ "id": 3056855323772677
+ },
+ {
+ "id": 3056855168075525
+ },
+ {
+ "id": 3056853824636741
+ },
+ {
+ "id": 3056845534496581
+ },
+ {
+ "id": 3056841521432389
+ },
+ {
+ "id": 3056824947361477
+ },
+ {
+ "id": 3056818300438277
+ },
+ {
+ "id": 3056812008179397
+ },
+ {
+ "id": 3056800490489541
+ },
+ {
+ "id": 3056795882260293
+ },
+ {
+ "id": 3056794358728453
+ },
+ {
+ "id": 3056793028560773
+ },
+ {
+ "id": 3056787826083717
+ },
+ {
+ "id": 3056787197740869
+ },
+ {
+ "id": 3056782149093125
+ },
+ {
+ "id": 3056777045722949
+ },
+ {
+ "id": 3056766262232837
+ },
+ {
+ "id": 3056764011890501
+ },
+ {
+ "id": 3056763779942213
+ },
+ {
+ "id": 3056757018216197
+ },
+ {
+ "id": 3056750324418245
+ },
+ {
+ "id": 3056733706979077
+ },
+ {
+ "id": 3056727891347269
+ },
+ {
+ "id": 3056727790389061
+ },
+ {
+ "id": 3056727670687621
+ },
+ {
+ "id": 3056720378021765
+ },
+ {
+ "id": 3056698846840581
+ },
+ {
+ "id": 3056698575456005
+ },
+ {
+ "id": 3056693096744837
+ },
+ {
+ "id": 3056692115998533
+ },
+ {
+ "id": 3056687143307013
+ },
+ {
+ "id": 3056685239076613
+ },
+ {
+ "id": 3056681319761733
+ },
+ {
+ "id": 3056668773107461
+ },
+ {
+ "id": 3056664984225669
+ },
+ {
+ "id": 3056661416232837
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3055176918828421
+ },
+ {
+ "id": 3054195561631109
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3055567606646661
+ },
+ {
+ "id": 3055177241628037
+ },
+ {
+ "id": 3055176919745925
+ },
+ {
+ "id": 3054195913755845
+ },
+ {
+ "id": 3054195562007941
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 84,
+ "missing_samples": [
+ {
+ "id": 3057420695603013
+ },
+ {
+ "id": 3057420695390021
+ },
+ {
+ "id": 3057333869315909
+ },
+ {
+ "id": 3057214123050821
+ },
+ {
+ "id": 3057102065273221
+ },
+ {
+ "id": 3057069836568261
+ },
+ {
+ "id": 3057069559318213
+ },
+ {
+ "id": 3057068421285573
+ },
+ {
+ "id": 3057046178219845
+ },
+ {
+ "id": 3056982205843269
+ },
+ {
+ "id": 3056982205630277
+ },
+ {
+ "id": 3056956399159173
+ },
+ {
+ "id": 3056890526271301
+ },
+ {
+ "id": 3056889936807685
+ },
+ {
+ "id": 3056884949944197
+ },
+ {
+ "id": 3056794935265093
+ },
+ {
+ "id": 3056724792837957
+ },
+ {
+ "id": 3056715342644998
+ },
+ {
+ "id": 3056525075613445
+ },
+ {
+ "id": 3056506564429573
+ },
+ {
+ "id": 3055890044389125
+ },
+ {
+ "id": 3055885299271365
+ },
+ {
+ "id": 3055858040621125
+ },
+ {
+ "id": 3055855807367045
+ },
+ {
+ "id": 3055854195361477
+ },
+ {
+ "id": 3055852808914693
+ },
+ {
+ "id": 3055774607657029
+ },
+ {
+ "id": 3055763984451333
+ },
+ {
+ "id": 3055763984221957
+ },
+ {
+ "id": 3055757788825285
+ },
+ {
+ "id": 3055757043795781
+ },
+ {
+ "id": 3055639809738501
+ },
+ {
+ "id": 3055629230081861
+ },
+ {
+ "id": 3055598627915461
+ },
+ {
+ "id": 3055594099394565
+ },
+ {
+ "id": 3055593873819397
+ },
+ {
+ "id": 3055568805889925
+ },
+ {
+ "id": 3055567467775877
+ },
+ {
+ "id": 3055398349588165
+ },
+ {
+ "id": 3055365207852805
+ },
+ {
+ "id": 3055356105049861
+ },
+ {
+ "id": 3055354347685573
+ },
+ {
+ "id": 3055215423655301
+ },
+ {
+ "id": 3055178207153925
+ },
+ {
+ "id": 3055177880128581
+ },
+ {
+ "id": 3055177166523781
+ },
+ {
+ "id": 3054532494724421
+ },
+ {
+ "id": 3054369725648197
+ },
+ {
+ "id": 3054369201130885
+ },
+ {
+ "id": 3054282268888133
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 13,
+ "records_with_pk": 13,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3055852804769541
+ },
+ {
+ "id": 3055757040240453
+ },
+ {
+ "id": 3055567463532421
+ },
+ {
+ "id": 3055177162837381
+ },
+ {
+ "id": 3054210385137029
+ },
+ {
+ "id": 3054195772001605
+ },
+ {
+ "id": 3053966621347013
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 316,
+ "missing_samples": [
+ {
+ "id": 3057270102296453
+ },
+ {
+ "id": 3057270102296454
+ },
+ {
+ "id": 3057270102296455
+ },
+ {
+ "id": 3057270102296456
+ },
+ {
+ "id": 3057270102296457
+ },
+ {
+ "id": 3057156450977669
+ },
+ {
+ "id": 3057134774388613
+ },
+ {
+ "id": 3057078870181637
+ },
+ {
+ "id": 3057048528390021
+ },
+ {
+ "id": 3057043857180485
+ },
+ {
+ "id": 3057015007889221
+ },
+ {
+ "id": 3057013774731077
+ },
+ {
+ "id": 3057008535111493
+ },
+ {
+ "id": 3056995705620293
+ },
+ {
+ "id": 3056959702091525
+ },
+ {
+ "id": 3056954954352325
+ },
+ {
+ "id": 3056943961081669
+ },
+ {
+ "id": 3056943961065285
+ },
+ {
+ "id": 3056938840458949
+ },
+ {
+ "id": 3056938840458950
+ },
+ {
+ "id": 3056938840458951
+ },
+ {
+ "id": 3056932669966149
+ },
+ {
+ "id": 3056931820734149
+ },
+ {
+ "id": 3056914461689541
+ },
+ {
+ "id": 3056914283038405
+ },
+ {
+ "id": 3056905348155141
+ },
+ {
+ "id": 3056902090180357
+ },
+ {
+ "id": 3056891126744965
+ },
+ {
+ "id": 3056891126761349
+ },
+ {
+ "id": 3056886266480389
+ },
+ {
+ "id": 3056884237829829
+ },
+ {
+ "id": 3056884237846213
+ },
+ {
+ "id": 3056877437814661
+ },
+ {
+ "id": 3056864357205765
+ },
+ {
+ "id": 3056864357205766
+ },
+ {
+ "id": 3056855001810693
+ },
+ {
+ "id": 3056853945599685
+ },
+ {
+ "id": 3056852579862405
+ },
+ {
+ "id": 3056837046994693
+ },
+ {
+ "id": 3056836324624197
+ },
+ {
+ "id": 3056826114819973
+ },
+ {
+ "id": 3056816588408581
+ },
+ {
+ "id": 3056816588424965
+ },
+ {
+ "id": 3056809300887237
+ },
+ {
+ "id": 3056805524244293
+ },
+ {
+ "id": 3056779347511173
+ },
+ {
+ "id": 3056779174823813
+ },
+ {
+ "id": 3056779174823814
+ },
+ {
+ "id": 3056774520473477
+ },
+ {
+ "id": 3056774520473478
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 688,
+ "records_with_pk": 688,
+ "missing": 496,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3057033942206213
+ },
+ {
+ "sitegoodsstockid": 3057020049737477
+ },
+ {
+ "sitegoodsstockid": 3057014058862405
+ },
+ {
+ "sitegoodsstockid": 3057009674340165
+ },
+ {
+ "sitegoodsstockid": 3057005598492421
+ },
+ {
+ "sitegoodsstockid": 3057004882659141
+ },
+ {
+ "sitegoodsstockid": 3056997868406661
+ },
+ {
+ "sitegoodsstockid": 3056979367380805
+ },
+ {
+ "sitegoodsstockid": 3056967704184645
+ },
+ {
+ "sitegoodsstockid": 3056961133971333
+ },
+ {
+ "sitegoodsstockid": 3056949671331589
+ },
+ {
+ "sitegoodsstockid": 3056911529903941
+ },
+ {
+ "sitegoodsstockid": 3056911312242565
+ },
+ {
+ "sitegoodsstockid": 3056910612252485
+ },
+ {
+ "sitegoodsstockid": 3056910612776773
+ },
+ {
+ "sitegoodsstockid": 3056910613432133
+ },
+ {
+ "sitegoodsstockid": 3056890725517061
+ },
+ {
+ "sitegoodsstockid": 3056888105731845
+ },
+ {
+ "sitegoodsstockid": 3056888105895685
+ },
+ {
+ "sitegoodsstockid": 3056887950313349
+ },
+ {
+ "sitegoodsstockid": 3056884951287685
+ },
+ {
+ "sitegoodsstockid": 3056881394812805
+ },
+ {
+ "sitegoodsstockid": 3056868923803461
+ },
+ {
+ "sitegoodsstockid": 3056867086780165
+ },
+ {
+ "sitegoodsstockid": 3056867087369989
+ },
+ {
+ "sitegoodsstockid": 3056867086010117
+ },
+ {
+ "sitegoodsstockid": 3056866232600261
+ },
+ {
+ "sitegoodsstockid": 3056850159027973
+ },
+ {
+ "sitegoodsstockid": 3056847869511429
+ },
+ {
+ "sitegoodsstockid": 3056847870068485
+ },
+ {
+ "sitegoodsstockid": 3056837533452037
+ },
+ {
+ "sitegoodsstockid": 3056837532845829
+ },
+ {
+ "sitegoodsstockid": 3056811220617093
+ },
+ {
+ "sitegoodsstockid": 3056811220453253
+ },
+ {
+ "sitegoodsstockid": 3056808611137349
+ },
+ {
+ "sitegoodsstockid": 3056805312218885
+ },
+ {
+ "sitegoodsstockid": 3056805313136389
+ },
+ {
+ "sitegoodsstockid": 3056805312694021
+ },
+ {
+ "sitegoodsstockid": 3056804676077445
+ },
+ {
+ "sitegoodsstockid": 3056804675569541
+ },
+ {
+ "sitegoodsstockid": 3056797925508869
+ },
+ {
+ "sitegoodsstockid": 3056797925984005
+ },
+ {
+ "sitegoodsstockid": 3056797925017349
+ },
+ {
+ "sitegoodsstockid": 3056796414658245
+ },
+ {
+ "sitegoodsstockid": 3056796414822085
+ },
+ {
+ "sitegoodsstockid": 3056794178750341
+ },
+ {
+ "sitegoodsstockid": 3056794002392837
+ },
+ {
+ "sitegoodsstockid": 3056776751368005
+ },
+ {
+ "sitegoodsstockid": 3056753449502597
+ },
+ {
+ "sitegoodsstockid": 3056753449994117
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053572251340677
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 56,
+ "missing_samples": [
+ {
+ "id": 3057420702877509
+ },
+ {
+ "id": 3057420702828357
+ },
+ {
+ "id": 3057290456647557
+ },
+ {
+ "id": 3057196644845317
+ },
+ {
+ "id": 3057167232796421
+ },
+ {
+ "id": 3057069563741893
+ },
+ {
+ "id": 3057068425086661
+ },
+ {
+ "id": 3057052575090373
+ },
+ {
+ "id": 3057046180955973
+ },
+ {
+ "id": 3056956402583429
+ },
+ {
+ "id": 3056953998591877
+ },
+ {
+ "id": 3056953998542725
+ },
+ {
+ "id": 3056919599646533
+ },
+ {
+ "id": 3056911096579973
+ },
+ {
+ "id": 3056890529875781
+ },
+ {
+ "id": 3056889940182789
+ },
+ {
+ "id": 3056880173565765
+ },
+ {
+ "id": 3056880173631301
+ },
+ {
+ "id": 3056853684012741
+ },
+ {
+ "id": 3056715346052869
+ },
+ {
+ "id": 3056714098034501
+ },
+ {
+ "id": 3056525609846533
+ },
+ {
+ "id": 3056506571310853
+ },
+ {
+ "id": 3055885303826117
+ },
+ {
+ "id": 3055854200489669
+ },
+ {
+ "id": 3055763989219077
+ },
+ {
+ "id": 3055757795428037
+ },
+ {
+ "id": 3055681673316165
+ },
+ {
+ "id": 3055679770003205
+ },
+ {
+ "id": 3055639815849733
+ },
+ {
+ "id": 3055639815898885
+ },
+ {
+ "id": 3055634624120645
+ },
+ {
+ "id": 3055629234423621
+ },
+ {
+ "id": 3055540093290245
+ },
+ {
+ "id": 3055225050172485
+ },
+ {
+ "id": 3055215426702725
+ },
+ {
+ "id": 3055177884388421
+ },
+ {
+ "id": 3055173781015941
+ },
+ {
+ "id": 3054532501458245
+ },
+ {
+ "id": 3054282273492037
+ },
+ {
+ "id": 3054276256615749
+ },
+ {
+ "id": 3054270334012741
+ },
+ {
+ "id": 3054257701309509
+ },
+ {
+ "id": 3054221961874629
+ },
+ {
+ "id": 3054210804370629
+ },
+ {
+ "id": 3054205940256133
+ },
+ {
+ "id": 3054189600066886
+ },
+ {
+ "id": 3054188845255877
+ },
+ {
+ "id": 3054140558675141
+ },
+ {
+ "id": 3054140558920901
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3053571772270213
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 554,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 554,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 2587,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:08:56.962352+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17227,
+ "diff": -17226
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 120,
+ "diff": -120
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 64,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 552,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 406040.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22075,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 120,
+ "ods": 120,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 3910.16,
+ "ods_sum": 3910.16,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17482.25,
+ "ods_sum": 17482.25,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1857.77,
+ "ods_sum": 1857.77,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 9785.64,
+ "ods_sum": 9785.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 305990.47,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2654,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14270.54,
+ "ods_sum": 14270.54,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4681,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 88,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4502,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 87,
+ "ods": 87,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4940.0,
+ "ods_sum": 4940.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 4855.76,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10545,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4584.0,
+ "ods_sum": 4584.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16086,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 433,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 136,
+ "ods": 136,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 32589.0,
+ "ods_sum": 32589.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 42,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 466822
+ },
+ "generated_at": "2026-01-19T07:09:03.345493+08:00"
+ }
+ ],
+ "total_missing": 34614,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:09:03.345546+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260119_082915.json b/etl_billiards/reports/data_integrity_history_20260119_082915.json
new file mode 100644
index 0000000..da06d04
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260119_082915.json
@@ -0,0 +1,24517 @@
+{
+ "mode": "history",
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "label": "month_2024-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-07-19T00:00:00+08:00",
+ "end": "2024-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 13,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:36:45.707440+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:36:56.167144+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "label": "month_2024-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-08-01T00:00:00+08:00",
+ "end": "2024-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:39:11.088512+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:39:21.514836+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "label": "month_2024-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-09-01T00:00:00+08:00",
+ "end": "2024-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:41:37.162810+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:41:47.077781+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "label": "month_2024-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-10-01T00:00:00+08:00",
+ "end": "2024-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:44:02.517955+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:44:13.078380+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "label": "month_2024-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-11-01T00:00:00+08:00",
+ "end": "2024-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:46:29.655689+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:46:40.111494+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "label": "month_2024-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2024-12-01T00:00:00+08:00",
+ "end": "2025-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:48:52.417950+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:49:02.521291+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "label": "month_2025-01-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:51:15.362870+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:51:26.056095+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "label": "month_2025-02-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 28,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:53:40.905795+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:53:51.454575+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "label": "month_2025-03-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:56:05.319847+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:56:15.821734+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "label": "month_2025-04-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T07:58:29.552232+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T07:58:39.602961+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "label": "month_2025-05-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:00:54.482073+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T08:01:04.790663+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "label": "month_2025-06-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8332,
+ "records_with_pk": 8332,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1674,
+ "records_with_pk": 1674,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:03:17.107093+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 464365
+ },
+ "generated_at": "2026-01-19T08:03:27.049723+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1776,
+ "records_with_pk": 1776,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9969,
+ "records_with_pk": 9969,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 351,
+ "records_with_pk": 351,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11946,
+ "records_with_pk": 11946,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2551,
+ "records_with_pk": 2551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1845,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 1845,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:06:53.838853+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463119
+ },
+ "generated_at": "2026-01-19T08:07:03.991335+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4602,
+ "records_with_pk": 4602,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 859,
+ "records_with_pk": 859,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 94,
+ "records_with_pk": 94,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5196,
+ "records_with_pk": 5196,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4763,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 24,
+ "skipped_missing_pk": 4763,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:09:53.937608+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 460778
+ },
+ "generated_at": "2026-01-19T08:10:04.668039+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3720,
+ "records_with_pk": 3720,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 19,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 654,
+ "records_with_pk": 654,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4816,
+ "records_with_pk": 4816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3810,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3810,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:13:03.304940+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 240,
+ "ods": 654,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 391.51,
+ "ods_sum": 781.44,
+ "diff": -389.93000000000006
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 69566.69,
+ "ods_sum": 192541.75,
+ "diff": -122975.06
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 462687
+ },
+ "generated_at": "2026-01-19T08:13:13.481155+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1435,
+ "records_with_pk": 1435,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 259,
+ "records_with_pk": 259,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2019,
+ "records_with_pk": 2019,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1462,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 1462,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:15:46.480592+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 461541
+ },
+ "generated_at": "2026-01-19T08:15:56.711886+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3874,
+ "records_with_pk": 3874,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 884,
+ "records_with_pk": 884,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5516,
+ "records_with_pk": 5516,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3999,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 20,
+ "skipped_missing_pk": 3999,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:18:42.768538+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 461029
+ },
+ "generated_at": "2026-01-19T08:18:53.200611+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4011,
+ "records_with_pk": 4011,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 975,
+ "records_with_pk": 975,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5464,
+ "records_with_pk": 5464,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4118,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 4118,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:21:41.547645+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 460886
+ },
+ "generated_at": "2026-01-19T08:21:51.631109+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 800,
+ "records_with_pk": 800,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 157,
+ "records_with_pk": 157,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 823,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 823,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:24:10.237193+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463666
+ },
+ "generated_at": "2026-01-19T08:24:20.536791+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 767,
+ "records_with_pk": 767,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 188,
+ "records_with_pk": 188,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1198,
+ "records_with_pk": 1198,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 790,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 790,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:26:37.733093+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 463693
+ },
+ "generated_at": "2026-01-19T08:26:47.627441+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 67,
+ "records_with_pk": 67,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 531,
+ "records_with_pk": 531,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9833,
+ "records_with_pk": 9833,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 114,
+ "records_with_pk": 114,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16403,
+ "records_with_pk": 16403,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2445,
+ "records_with_pk": 2445,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 13,
+ "records_with_pk": 13,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 688,
+ "records_with_pk": 688,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1664,
+ "records_with_pk": 1664,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 554,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 554,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:29:05.648926+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17601,
+ "diff": -17600
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 472,
+ "diff": -472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 64,
+ "ods": 67,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 3,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 552,
+ "ods": 554,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 938,
+ "ods": 943,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 406040.3,
+ "ods_sum": 411958.35,
+ "diff": -5918.049999999988
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 7,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 169,
+ "ods": 170,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22075,
+ "ods": 22478,
+ "diff": -403
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 120,
+ "ods": 472,
+ "diff": -352
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 3910.16,
+ "ods_sum": 8371.97,
+ "diff": -4461.8099999999995
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 24549.66,
+ "diff": -19693.9
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17482.25,
+ "ods_sum": 53245.25,
+ "diff": -35763.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1857.77,
+ "ods_sum": 4127.64,
+ "diff": -2269.8700000000003
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 9785.64,
+ "ods_sum": 23662.8,
+ "diff": -13877.16
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17227,
+ "ods": 17601,
+ "diff": -374
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 305990.47,
+ "ods_sum": 311771.56,
+ "diff": -5781.090000000026
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2654,
+ "ods": 2710,
+ "diff": -56
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 501714,
+ "ods": 17563,
+ "diff": 484151
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 615278.9,
+ "ods_sum": 21673.2,
+ "diff": 593605.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 114,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14270.54,
+ "ods_sum": 35457.3,
+ "diff": -21186.760000000002
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4681,
+ "ods": 4755,
+ "diff": -74
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 88,
+ "ods": 92,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4502,
+ "ods": 4586,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 87,
+ "ods": 393,
+ "diff": -306
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4940.0,
+ "ods_sum": 25170.0,
+ "diff": -20230.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4855.76,
+ "ods_sum": 24549.66,
+ "diff": -19693.9
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10545,
+ "ods": 10861,
+ "diff": -316
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 395,
+ "diff": -315
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4584.0,
+ "ods_sum": 25438.0,
+ "diff": -20854.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16086,
+ "ods": 16403,
+ "diff": -317
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 433,
+ "ods": 440,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 136,
+ "ods": 554,
+ "diff": -418
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 32589.0,
+ "ods_sum": 62078.0,
+ "diff": -29489.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": -34.0,
+ "diff": 34.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 42,
+ "ods": 43,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 462416
+ },
+ "generated_at": "2026-01-19T08:29:15.504991+08:00"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T08:29:15.505020+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260119_170701.json b/etl_billiards/reports/data_integrity_history_20260119_170701.json
new file mode 100644
index 0000000..d54e49a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260119_170701.json
@@ -0,0 +1,9 @@
+{
+ "mode": "history",
+ "start": "2026-01-19T00:00:00+08:00",
+ "end": "2026-01-19T00:00:00+08:00",
+ "windows": [],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T17:07:01.451073+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260120_041412.json b/etl_billiards/reports/data_integrity_history_20260120_041412.json
new file mode 100644
index 0000000..1d4ba7a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260120_041412.json
@@ -0,0 +1,10555 @@
+{
+ "mode": "history",
+ "start": "2025-07-20T00:00:00+08:00",
+ "end": "2026-01-20T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-20T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-19T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 12,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1790,
+ "records_with_pk": 1790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11894,
+ "records_with_pk": 11894,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2514,
+ "records_with_pk": 2514,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 14,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1858,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 1858,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T03:51:30.040626+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 465,
+ "ods": 465,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 747,
+ "ods": 747,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 8,
+ "ods": 8,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 570590
+ },
+ "generated_at": "2026-01-20T03:51:37.115550+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11894,
+ "records_with_pk": 11894,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T03:54:31.172192+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 568249
+ },
+ "generated_at": "2026-01-20T03:54:37.871489+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11894,
+ "records_with_pk": 11894,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T03:57:25.939452+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 240,
+ "ods": 654,
+ "diff": -414
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 391.51,
+ "ods_sum": 781.44,
+ "diff": -389.93000000000006
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 69566.69,
+ "ods_sum": 192541.75,
+ "diff": -122975.06
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 570158
+ },
+ "generated_at": "2026-01-20T03:57:32.703985+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1476,
+ "records_with_pk": 1476,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 269,
+ "records_with_pk": 269,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2059,
+ "records_with_pk": 2059,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1504,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 1504,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:00:03.134754+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 569012
+ },
+ "generated_at": "2026-01-20T04:00:09.851638+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:02:57.794632+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 568500
+ },
+ "generated_at": "2026-01-20T04:03:04.513892+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:06:44.629763+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 568357
+ },
+ "generated_at": "2026-01-20T04:06:55.377324+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:09:15.263506+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 571137
+ },
+ "generated_at": "2026-01-20T04:09:22.967307+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:11:41.642798+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 571164
+ },
+ "generated_at": "2026-01-20T04:11:49.388911+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-20T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-20T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 700,
+ "records_with_pk": 700,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058686745823045
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 869,
+ "records_with_pk": 869,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 728,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 728,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:14:04.703641+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 17711,
+ "diff": -17710
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 579,
+ "diff": -579
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554,
+ "ods": 554,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 943,
+ "ods": 943,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 411958.35,
+ "ods_sum": 411958.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 579,
+ "ods": 579,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 12066.07,
+ "ods_sum": 12066.07,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 29828.36,
+ "ods_sum": 29828.36,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 68332.42,
+ "ods_sum": 68332.42,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 4379.2,
+ "ods_sum": 4379.2,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30028.73,
+ "ods_sum": 30028.73,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 153,
+ "ods": 153,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 51898.0,
+ "ods_sum": 51898.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 474,
+ "ods": 474,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 30844.0,
+ "ods_sum": 30844.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 29828.36,
+ "ods_sum": 29828.36,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 474,
+ "ods": 474,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 30824.0,
+ "ods_sum": 30824.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 678,
+ "ods": 678,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 82556.0,
+ "ods_sum": 82556.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 571257
+ },
+ "generated_at": "2026-01-20T04:14:12.384754+08:00"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T04:14:12.384777+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_061648.json b/etl_billiards/reports/data_integrity_history_20260126_061648.json
new file mode 100644
index 0000000..ceff579
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_061648.json
@@ -0,0 +1,19348 @@
+{
+ "mode": "history",
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "label": "month_2025-01-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2024-12-31T22:00:00+08:00",
+ "end": "2025-02-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1738,
+ "records_with_pk": 1738,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T04:44:50.286736+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T04:44:54.113987+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "label": "month_2025-02-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-01-31T22:00:00+08:00",
+ "end": "2025-03-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 28,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1738,
+ "records_with_pk": 1738,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T04:50:54.915246+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T04:50:58.640259+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "label": "month_2025-03-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-02-28T22:00:00+08:00",
+ "end": "2025-04-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1738,
+ "records_with_pk": 1738,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T04:56:40.233217+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T04:56:43.957627+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "label": "month_2025-04-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-03-31T22:00:00+08:00",
+ "end": "2025-05-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1738,
+ "records_with_pk": 1738,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:02:32.502900+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T05:02:36.144485+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "label": "month_2025-05-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-04-30T22:00:00+08:00",
+ "end": "2025-06-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1738,
+ "records_with_pk": 1738,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:08:23.632374+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T05:08:27.290890+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "label": "month_2025-06-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-05-31T22:00:00+08:00",
+ "end": "2025-07-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10071,
+ "records_with_pk": 10071,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11928,
+ "records_with_pk": 11928,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 8,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:14:18.744652+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18382
+ },
+ "generated_at": "2026-01-26T05:14:22.563756+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10073,
+ "records_with_pk": 10073,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11929,
+ "records_with_pk": 11929,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 11,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:20:21.047786+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19628
+ },
+ "generated_at": "2026-01-26T05:20:24.799157+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 15,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:27:26.825587+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21969
+ },
+ "generated_at": "2026-01-26T05:27:30.496154+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 15,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:34:03.938323+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19646
+ },
+ "generated_at": "2026-01-26T05:34:07.598877+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 789,
+ "records_with_pk": 789,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 13,
+ "records_with_pk": 13,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1167,
+ "records_with_pk": 1167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 803,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 803,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 15,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:39:56.916120+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21206
+ },
+ "generated_at": "2026-01-26T05:40:00.785991+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:46:41.582600+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21718
+ },
+ "generated_at": "2026-01-26T05:46:45.166466+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 204,
+ "records_with_pk": 204,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:53:37.253537+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21861
+ },
+ "generated_at": "2026-01-26T05:53:40.872515+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T05:59:29.545308+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19081
+ },
+ "generated_at": "2026-01-26T05:59:33.346021+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T06:05:13.373633+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19054
+ },
+ "generated_at": "2026-01-26T06:05:17.001366+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T06:10:57.961411+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19158
+ },
+ "generated_at": "2026-01-26T06:11:01.735310+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 540,
+ "records_with_pk": 540,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10075,
+ "records_with_pk": 10075,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3067259091061957
+ },
+ {
+ "id": 3067259091078341
+ },
+ {
+ "id": 3067252823968965
+ },
+ {
+ "id": 3067252823985349
+ },
+ {
+ "id": 3067211608837061
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 147,
+ "records_with_pk": 147,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11930,
+ "records_with_pk": 11930,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067259086490821
+ },
+ {
+ "id": 3067252820446405
+ },
+ {
+ "id": 3067211605281733
+ },
+ {
+ "id": 3067210806709061
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067278947175045
+ },
+ {
+ "id": 3067259087146181
+ },
+ {
+ "id": 3067211605855173
+ },
+ {
+ "id": 3067210808216389
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 953,
+ "records_with_pk": 953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 551,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 551,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T06:16:45.330506+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18361,
+ "diff": -18360
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 465,
+ "diff": -465
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 465,
+ "ods": 465,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 9264.7,
+ "ods_sum": 9264.7,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 21930.18,
+ "ods_sum": 21930.18,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 61454.19,
+ "ods_sum": 61454.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 28610.12,
+ "ods_sum": 28610.12,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 138,
+ "ods": 138,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 40013.33,
+ "ods_sum": 40013.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 317,
+ "ods": 331,
+ "diff": -14
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 21728.0,
+ "ods_sum": 22654.0,
+ "diff": -926.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 21004.18,
+ "ods_sum": 21930.18,
+ "diff": -926.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 330,
+ "ods": 330,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 22452.0,
+ "ods_sum": 22452.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 524,
+ "ods": 524,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 59984.0,
+ "ods_sum": 59984.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18861
+ },
+ "generated_at": "2026-01-26T06:16:48.949911+08:00"
+ }
+ ],
+ "total_missing": 190,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T06:16:48.949931+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_192038.json b/etl_billiards/reports/data_integrity_history_20260126_192038.json
new file mode 100644
index 0000000..a916e74
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_192038.json
@@ -0,0 +1,18946 @@
+{
+ "mode": "history",
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-01-01T00:00:00+08:00",
+ "end": "2025-02-01T00:00:00+08:00",
+ "label": "month_2025-01-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2024-12-31T22:00:00+08:00",
+ "end": "2025-02-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9939,
+ "records_with_pk": 9939,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16977,
+ "records_with_pk": 16977,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8160,
+ "records_with_pk": 8160,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:38:49.722107+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:38:57.643275+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-02-01T00:00:00+08:00",
+ "end": "2025-03-01T00:00:00+08:00",
+ "label": "month_2025-02-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-01-31T22:00:00+08:00",
+ "end": "2025-03-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 28,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9939,
+ "records_with_pk": 9939,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16977,
+ "records_with_pk": 16977,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8160,
+ "records_with_pk": 8160,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:41:25.769291+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:41:33.883748+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-03-01T00:00:00+08:00",
+ "end": "2025-04-01T00:00:00+08:00",
+ "label": "month_2025-03-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-02-28T22:00:00+08:00",
+ "end": "2025-04-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9939,
+ "records_with_pk": 9939,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16977,
+ "records_with_pk": 16977,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8160,
+ "records_with_pk": 8160,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:44:05.340888+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:44:13.179324+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-04-01T00:00:00+08:00",
+ "end": "2025-05-01T00:00:00+08:00",
+ "label": "month_2025-04-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-03-31T22:00:00+08:00",
+ "end": "2025-05-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9939,
+ "records_with_pk": 9939,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16977,
+ "records_with_pk": 16977,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:46:43.078754+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:46:50.930848+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-05-01T00:00:00+08:00",
+ "end": "2025-06-01T00:00:00+08:00",
+ "label": "month_2025-05-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-04-30T22:00:00+08:00",
+ "end": "2025-06-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16978,
+ "records_with_pk": 16978,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:49:22.666606+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:49:30.492059+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-06-01T00:00:00+08:00",
+ "end": "2025-07-01T00:00:00+08:00",
+ "label": "month_2025-06-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-05-31T22:00:00+08:00",
+ "end": "2025-07-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16978,
+ "records_with_pk": 16978,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:51:59.529360+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18368
+ },
+ "generated_at": "2026-01-26T18:52:07.305231+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16978,
+ "records_with_pk": 16978,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:54:52.477989+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19614
+ },
+ "generated_at": "2026-01-26T18:55:00.181811+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16978,
+ "records_with_pk": 16978,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:58:09.968647+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21955
+ },
+ "generated_at": "2026-01-26T18:58:17.626016+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16978,
+ "records_with_pk": 16978,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:01:18.117991+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19632
+ },
+ "generated_at": "2026-01-26T19:01:25.909968+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16979,
+ "records_with_pk": 16979,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:03:53.935724+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21192
+ },
+ "generated_at": "2026-01-26T19:04:01.765414+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16979,
+ "records_with_pk": 16979,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:07:00.229045+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21704
+ },
+ "generated_at": "2026-01-26T19:07:07.983588+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16979,
+ "records_with_pk": 16979,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:10:07.271731+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21847
+ },
+ "generated_at": "2026-01-26T19:10:14.988226+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16980,
+ "records_with_pk": 16980,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068078500645061
+ },
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:12:45.645937+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19067
+ },
+ "generated_at": "2026-01-26T19:12:53.309926+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16980,
+ "records_with_pk": 16980,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068078500645061
+ },
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:15:20.585365+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19040
+ },
+ "generated_at": "2026-01-26T19:15:28.732577+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16980,
+ "records_with_pk": 16980,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068078500645061
+ },
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:17:54.522162+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19144
+ },
+ "generated_at": "2026-01-26T19:18:02.558874+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 540,
+ "records_with_pk": 540,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985350341
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 147,
+ "records_with_pk": 147,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11771,
+ "records_with_pk": 11771,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052983007429
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16981,
+ "records_with_pk": 16981,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068085950662789
+ },
+ {
+ "id": 3068078500645061
+ },
+ {
+ "id": 3068068669081733
+ },
+ {
+ "id": 3068054386329861
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8161,
+ "records_with_pk": 8161,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068052985891013
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 953,
+ "records_with_pk": 953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 551,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 551,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 7,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:20:30.475266+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18386,
+ "diff": -18385
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 465,
+ "diff": -465
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 465,
+ "ods": 465,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 9264.7,
+ "ods_sum": 9264.7,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 21930.18,
+ "ods_sum": 21930.18,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 61454.19,
+ "ods_sum": 61454.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 28610.12,
+ "ods_sum": 28610.12,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 138,
+ "ods": 138,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 40013.33,
+ "ods_sum": 40013.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 331,
+ "ods": 331,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 22654.0,
+ "ods_sum": 22654.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 21930.18,
+ "ods_sum": 21930.18,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11427,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 330,
+ "ods": 330,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 22452.0,
+ "ods_sum": 22452.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 524,
+ "ods": 524,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 59984.0,
+ "ods_sum": 59984.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18833
+ },
+ "generated_at": "2026-01-26T19:20:38.513902+08:00"
+ }
+ ],
+ "total_missing": 61,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T19:20:38.513921+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_205212.json b/etl_billiards/reports/data_integrity_history_20260126_205212.json
new file mode 100644
index 0000000..c9a05e0
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_205212.json
@@ -0,0 +1,11273 @@
+{
+ "mode": "history",
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9950,
+ "records_with_pk": 9950,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11780,
+ "records_with_pk": 11780,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16994,
+ "records_with_pk": 16994,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1736,
+ "records_with_pk": 1736,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:25:56.834455+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:26:03.152991+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9950,
+ "records_with_pk": 9950,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11780,
+ "records_with_pk": 11780,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16994,
+ "records_with_pk": 16994,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1736,
+ "records_with_pk": 1736,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:29:15.544082+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:29:21.794699+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9950,
+ "records_with_pk": 9950,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11781,
+ "records_with_pk": 11781,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16996,
+ "records_with_pk": 16996,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2461,
+ "records_with_pk": 2461,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1736,
+ "records_with_pk": 1736,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 43,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:32:27.027380+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:32:33.303569+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9950,
+ "records_with_pk": 9950,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11781,
+ "records_with_pk": 11781,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16996,
+ "records_with_pk": 16996,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2461,
+ "records_with_pk": 2461,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1736,
+ "records_with_pk": 1736,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 44,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:35:06.503546+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:35:12.766478+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9951,
+ "records_with_pk": 9951,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11782,
+ "records_with_pk": 11782,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16997,
+ "records_with_pk": 16997,
+ "missing": 16,
+ "missing_samples": [
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2462,
+ "records_with_pk": 2462,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1736,
+ "records_with_pk": 1736,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 48,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:38:15.896628+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:38:22.103506+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9951,
+ "records_with_pk": 9951,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11782,
+ "records_with_pk": 11782,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16998,
+ "records_with_pk": 16998,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2462,
+ "records_with_pk": 2462,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1737,
+ "records_with_pk": 1737,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 50,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:41:29.899345+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:41:36.487590+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9952,
+ "records_with_pk": 9952,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11783,
+ "records_with_pk": 11783,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17000,
+ "records_with_pk": 17000,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2462,
+ "records_with_pk": 2462,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1737,
+ "records_with_pk": 1737,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 54,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:44:11.129296+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:44:17.462058+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9952,
+ "records_with_pk": 9952,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11783,
+ "records_with_pk": 11783,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17000,
+ "records_with_pk": 17000,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2462,
+ "records_with_pk": 2462,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1739,
+ "records_with_pk": 1739,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 56,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:46:48.283138+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:46:54.495119+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9958,
+ "records_with_pk": 9958,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11785,
+ "records_with_pk": 11785,
+ "missing": 14,
+ "missing_samples": [
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17002,
+ "records_with_pk": 17002,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2464,
+ "records_with_pk": 2464,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 67,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:49:26.067583+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -6
+ },
+ "generated_at": "2026-01-26T20:49:32.338156+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T22:34:55.893505+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 585,
+ "records_with_pk": 585,
+ "missing": 16,
+ "missing_samples": [
+ {
+ "id": 3068173758433541
+ },
+ {
+ "id": 3068172788353285
+ },
+ {
+ "id": 3068172286822597
+ },
+ {
+ "id": 3068165730896197
+ },
+ {
+ "id": 3068161172441285
+ },
+ {
+ "id": 3068156440938821
+ },
+ {
+ "id": 3068147068373253
+ },
+ {
+ "id": 3068144643229829
+ },
+ {
+ "id": 3068137701460101
+ },
+ {
+ "id": 3068137475737733
+ },
+ {
+ "id": 3068136505919813
+ },
+ {
+ "id": 3068116726745285
+ },
+ {
+ "id": 3068116674398469
+ },
+ {
+ "id": 3068111450900741
+ },
+ {
+ "id": 3068092211972229
+ },
+ {
+ "id": 3068052938459333
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9958,
+ "records_with_pk": 9958,
+ "missing": 18,
+ "missing_samples": [
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 162,
+ "records_with_pk": 162,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068173056575621
+ },
+ {
+ "id": 3068173056116869
+ },
+ {
+ "id": 3068173055641733
+ },
+ {
+ "id": 3068172409686149
+ },
+ {
+ "id": 3068165922752773
+ },
+ {
+ "id": 3068161263503493
+ },
+ {
+ "id": 3068156522088773
+ },
+ {
+ "id": 3068137884190981
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11786,
+ "records_with_pk": 11786,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17002,
+ "records_with_pk": 17002,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2464,
+ "records_with_pk": 2464,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8169,
+ "records_with_pk": 8169,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1024,
+ "records_with_pk": 1024,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068173817415941
+ },
+ {
+ "sitegoodsstockid": 3068166835570885
+ },
+ {
+ "sitegoodsstockid": 3068165128079621
+ },
+ {
+ "sitegoodsstockid": 3068159660001413
+ },
+ {
+ "sitegoodsstockid": 3068158269720838
+ },
+ {
+ "sitegoodsstockid": 3068158132488389
+ },
+ {
+ "sitegoodsstockid": 3068143580711045
+ },
+ {
+ "sitegoodsstockid": 3068142510311621
+ },
+ {
+ "sitegoodsstockid": 3068142511032517
+ },
+ {
+ "sitegoodsstockid": 3068135950321861
+ },
+ {
+ "sitegoodsstockid": 3068135950846149
+ },
+ {
+ "sitegoodsstockid": 3068135276693829
+ },
+ {
+ "sitegoodsstockid": 3068135277218117
+ },
+ {
+ "sitegoodsstockid": 3068132803037509
+ },
+ {
+ "sitegoodsstockid": 3068126246095109
+ },
+ {
+ "sitegoodsstockid": 3068125658253573
+ },
+ {
+ "sitegoodsstockid": 3068096166971717
+ },
+ {
+ "sitegoodsstockid": 3068096166529349
+ },
+ {
+ "sitegoodsstockid": 3068090895648965
+ },
+ {
+ "sitegoodsstockid": 3068058833127621
+ },
+ {
+ "sitegoodsstockid": 3068045209585989
+ },
+ {
+ "sitegoodsstockid": 3068045210061125
+ },
+ {
+ "sitegoodsstockid": 3068033580435653
+ },
+ {
+ "sitegoodsstockid": 3068033136544069
+ },
+ {
+ "sitegoodsstockid": 3068032978126981
+ },
+ {
+ "sitegoodsstockid": 3068032978634885
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 598,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 598,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 122,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:52:05.443610+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 503,
+ "ods": 504,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 10412.32,
+ "ods_sum": 10412.32,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 23440.18,
+ "ods_sum": 23488.18,
+ "diff": -48.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66552.38,
+ "ods_sum": 66600.38,
+ "diff": -48.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 31050.69,
+ "ods_sum": 31050.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 150,
+ "ods": 150,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 45010.31,
+ "ods_sum": 45010.31,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 349,
+ "ods": 357,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 23828.0,
+ "ods_sum": 24212.0,
+ "diff": -384.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 23104.18,
+ "ods_sum": 23488.18,
+ "diff": -384.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 355,
+ "ods": 359,
+ "diff": -4
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 24424.0,
+ "ods_sum": 24742.0,
+ "diff": -318.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 567,
+ "ods": 568,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 66836.0,
+ "ods_sum": 66836.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -20
+ },
+ "generated_at": "2026-01-26T20:52:12.777070+08:00"
+ }
+ ],
+ "total_missing": 564,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T20:52:12.777091+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_213058.json b/etl_billiards/reports/data_integrity_history_20260126_213058.json
new file mode 100644
index 0000000..e10cf7a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_213058.json
@@ -0,0 +1,14940 @@
+{
+ "mode": "history",
+ "start": "2025-07-26T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-26T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-25T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 6,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1077,
+ "records_with_pk": 1077,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9962,
+ "records_with_pk": 9962,
+ "missing": 22,
+ "missing_samples": [
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 221,
+ "records_with_pk": 221,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11791,
+ "records_with_pk": 11791,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17007,
+ "records_with_pk": 17007,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 26,
+ "records_with_pk": 26,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8174,
+ "records_with_pk": 8174,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1219,
+ "records_with_pk": 1219,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1119,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 1119,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 90,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:06:10.863661+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 721,
+ "diff": -721
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 20,
+ "ods": 20,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 721,
+ "ods": 721,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11495.64,
+ "ods_sum": 11495.64,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38281.97,
+ "ods_sum": 38281.97,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 76905.95,
+ "ods_sum": 76905.95,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6771.92,
+ "ods_sum": 6771.92,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 27536.97,
+ "ods_sum": 27536.97,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 929,
+ "ods": 929,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 5.66,
+ "ods_sum": 5.66,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 19820.0,
+ "ods_sum": 19820.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 18387.0,
+ "ods_sum": 18387.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 203,
+ "ods": 203,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 766.09,
+ "ods_sum": 766.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65258.01,
+ "ods_sum": 65258.01,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 549,
+ "ods": 549,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 38816.0,
+ "ods_sum": 38816.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1051,
+ "ods": 1051,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 110117.0,
+ "ods_sum": 110117.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19096
+ },
+ "generated_at": "2026-01-26T21:06:14.707643+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9964,
+ "records_with_pk": 9964,
+ "missing": 24,
+ "missing_samples": [
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11792,
+ "records_with_pk": 11792,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17007,
+ "records_with_pk": 17007,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8174,
+ "records_with_pk": 8174,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 96,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:09:20.212001+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21962
+ },
+ "generated_at": "2026-01-26T21:09:24.059175+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11794,
+ "records_with_pk": 11794,
+ "missing": 23,
+ "missing_samples": [
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17008,
+ "records_with_pk": 17008,
+ "missing": 27,
+ "missing_samples": [
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8174,
+ "records_with_pk": 8174,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 103,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:12:19.753870+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19639
+ },
+ "generated_at": "2026-01-26T21:12:23.721895+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11794,
+ "records_with_pk": 11794,
+ "missing": 23,
+ "missing_samples": [
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17008,
+ "records_with_pk": 17008,
+ "missing": 27,
+ "missing_samples": [
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8174,
+ "records_with_pk": 8174,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 103,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:14:46.668961+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21199
+ },
+ "generated_at": "2026-01-26T21:14:50.516471+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11794,
+ "records_with_pk": 11794,
+ "missing": 23,
+ "missing_samples": [
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17009,
+ "records_with_pk": 17009,
+ "missing": 28,
+ "missing_samples": [
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8174,
+ "records_with_pk": 8174,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 104,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:17:52.264245+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21711
+ },
+ "generated_at": "2026-01-26T21:17:56.037437+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11795,
+ "records_with_pk": 11795,
+ "missing": 24,
+ "missing_samples": [
+ {
+ "id": 3068204085283013
+ },
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17009,
+ "records_with_pk": 17009,
+ "missing": 28,
+ "missing_samples": [
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8176,
+ "records_with_pk": 8176,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068205069404357
+ },
+ {
+ "id": 3068204090689733
+ },
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 107,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:20:56.597878+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21854
+ },
+ "generated_at": "2026-01-26T21:21:01.287237+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 27,
+ "missing_samples": [
+ {
+ "id": 3068205068568773
+ },
+ {
+ "id": 3068204090067141
+ },
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11796,
+ "records_with_pk": 11796,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068205065799877
+ },
+ {
+ "id": 3068204085283013
+ },
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17009,
+ "records_with_pk": 17009,
+ "missing": 28,
+ "missing_samples": [
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8176,
+ "records_with_pk": 8176,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068205069404357
+ },
+ {
+ "id": 3068204090689733
+ },
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 110,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:23:35.041502+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19074
+ },
+ "generated_at": "2026-01-26T21:23:38.763155+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9967,
+ "records_with_pk": 9967,
+ "missing": 27,
+ "missing_samples": [
+ {
+ "id": 3068205068568773
+ },
+ {
+ "id": 3068204090067141
+ },
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11796,
+ "records_with_pk": 11796,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3068205065799877
+ },
+ {
+ "id": 3068204085283013
+ },
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17010,
+ "records_with_pk": 17010,
+ "missing": 29,
+ "missing_samples": [
+ {
+ "id": 3068208146909445
+ },
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8178,
+ "records_with_pk": 8178,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3068210315135301
+ },
+ {
+ "id": 3068210315135302
+ },
+ {
+ "id": 3068205069404357
+ },
+ {
+ "id": 3068204090689733
+ },
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 113,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:26:03.247914+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19047
+ },
+ "generated_at": "2026-01-26T21:26:07.020272+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9968,
+ "records_with_pk": 9968,
+ "missing": 28,
+ "missing_samples": [
+ {
+ "id": 3068210314332485
+ },
+ {
+ "id": 3068205068568773
+ },
+ {
+ "id": 3068204090067141
+ },
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11797,
+ "records_with_pk": 11797,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3068210312022341
+ },
+ {
+ "id": 3068205065799877
+ },
+ {
+ "id": 3068204085283013
+ },
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17012,
+ "records_with_pk": 17012,
+ "missing": 31,
+ "missing_samples": [
+ {
+ "id": 3068211546622085
+ },
+ {
+ "id": 3068210794449157
+ },
+ {
+ "id": 3068208146909445
+ },
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8178,
+ "records_with_pk": 8178,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3068210315135301
+ },
+ {
+ "id": 3068210315135302
+ },
+ {
+ "id": 3068205069404357
+ },
+ {
+ "id": 3068204090689733
+ },
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 117,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:28:30.386946+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19151
+ },
+ "generated_at": "2026-01-26T21:28:34.665626+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T00:00:00+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 540,
+ "records_with_pk": 540,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9968,
+ "records_with_pk": 9968,
+ "missing": 28,
+ "missing_samples": [
+ {
+ "id": 3068210314332485
+ },
+ {
+ "id": 3068205068568773
+ },
+ {
+ "id": 3068204090067141
+ },
+ {
+ "id": 3068195098511621
+ },
+ {
+ "id": 3068191315953989
+ },
+ {
+ "id": 3068189905504453
+ },
+ {
+ "id": 3068187432765765
+ },
+ {
+ "id": 3068178372888901
+ },
+ {
+ "id": 3068178323785925
+ },
+ {
+ "id": 3068176796108933
+ },
+ {
+ "id": 3068173055166597
+ },
+ {
+ "id": 3068173055182981
+ },
+ {
+ "id": 3068173055199365
+ },
+ {
+ "id": 3068172409112709
+ },
+ {
+ "id": 3068172409145477
+ },
+ {
+ "id": 3068172409161861
+ },
+ {
+ "id": 3068165922326789
+ },
+ {
+ "id": 3068161263093893
+ },
+ {
+ "id": 3068147084101765
+ },
+ {
+ "id": 3068144682748165
+ },
+ {
+ "id": 3068137883715845
+ },
+ {
+ "id": 3068137496643781
+ },
+ {
+ "id": 3068136781121733
+ },
+ {
+ "id": 3068136781088965
+ },
+ {
+ "id": 3068116743686405
+ },
+ {
+ "id": 3068116691830917
+ },
+ {
+ "id": 3068111488747717
+ },
+ {
+ "id": 3068092242069701
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 147,
+ "records_with_pk": 147,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11797,
+ "records_with_pk": 11797,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3068210312022341
+ },
+ {
+ "id": 3068205065799877
+ },
+ {
+ "id": 3068204085283013
+ },
+ {
+ "id": 3068195094317317
+ },
+ {
+ "id": 3068193228065029
+ },
+ {
+ "id": 3068191313217861
+ },
+ {
+ "id": 3068189902260421
+ },
+ {
+ "id": 3068187430504773
+ },
+ {
+ "id": 3068178370578757
+ },
+ {
+ "id": 3068178321377477
+ },
+ {
+ "id": 3068176793585797
+ },
+ {
+ "id": 3068173815810309
+ },
+ {
+ "id": 3068173050710149
+ },
+ {
+ "id": 3068172403804293
+ },
+ {
+ "id": 3068165919459589
+ },
+ {
+ "id": 3068161259849861
+ },
+ {
+ "id": 3068156518615365
+ },
+ {
+ "id": 3068147081676933
+ },
+ {
+ "id": 3068144680323333
+ },
+ {
+ "id": 3068137880373509
+ },
+ {
+ "id": 3068137493563589
+ },
+ {
+ "id": 3068136777763013
+ },
+ {
+ "id": 3068116741064965
+ },
+ {
+ "id": 3068116689406085
+ },
+ {
+ "id": 3068111485782213
+ },
+ {
+ "id": 3068092239743173
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17012,
+ "records_with_pk": 17012,
+ "missing": 31,
+ "missing_samples": [
+ {
+ "id": 3068211546622085
+ },
+ {
+ "id": 3068210794449157
+ },
+ {
+ "id": 3068208146909445
+ },
+ {
+ "id": 3068199835715909
+ },
+ {
+ "id": 3068193998768325
+ },
+ {
+ "id": 3068188476033349
+ },
+ {
+ "id": 3068183718152325
+ },
+ {
+ "id": 3068182719219909
+ },
+ {
+ "id": 3068180288719109
+ },
+ {
+ "id": 3068179623479493
+ },
+ {
+ "id": 3068171775248517
+ },
+ {
+ "id": 3068171587406021
+ },
+ {
+ "id": 3068168069302533
+ },
+ {
+ "id": 3068166536087749
+ },
+ {
+ "id": 3068164968204421
+ },
+ {
+ "id": 3068160926992709
+ },
+ {
+ "id": 3068156135868741
+ },
+ {
+ "id": 3068154759743749
+ },
+ {
+ "id": 3068148319062213
+ },
+ {
+ "id": 3068146395908357
+ },
+ {
+ "id": 3068144802646213
+ },
+ {
+ "id": 3068143756839239
+ },
+ {
+ "id": 3068143756839238
+ },
+ {
+ "id": 3068143756839237
+ },
+ {
+ "id": 3068136318617733
+ },
+ {
+ "id": 3068128340887877
+ },
+ {
+ "id": 3068121241585925
+ },
+ {
+ "id": 3068118919940421
+ },
+ {
+ "id": 3068118229600453
+ },
+ {
+ "id": 3068113712285957
+ },
+ {
+ "id": 3068091996113029
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068195181201285
+ },
+ {
+ "id": 3068195094923525
+ },
+ {
+ "id": 3068193229965573
+ },
+ {
+ "id": 3068189902866629
+ },
+ {
+ "id": 3068173051381893
+ },
+ {
+ "id": 3068172404426885
+ },
+ {
+ "id": 3068161260423301
+ },
+ {
+ "id": 3068156519303493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8178,
+ "records_with_pk": 8178,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3068210315135301
+ },
+ {
+ "id": 3068210315135302
+ },
+ {
+ "id": 3068205069404357
+ },
+ {
+ "id": 3068204090689733
+ },
+ {
+ "id": 3068191316789573
+ },
+ {
+ "id": 3068187433306437
+ },
+ {
+ "id": 3068187433322821
+ },
+ {
+ "id": 3068178373445957
+ },
+ {
+ "id": 3068178324654277
+ },
+ {
+ "id": 3068176796911749
+ },
+ {
+ "id": 3068147084724357
+ },
+ {
+ "id": 3068137884977413
+ },
+ {
+ "id": 3068137497528517
+ },
+ {
+ "id": 3068116744390917
+ },
+ {
+ "id": 3068116692404357
+ },
+ {
+ "id": 3068111489616069
+ },
+ {
+ "id": 3068092242643141
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 953,
+ "records_with_pk": 953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068195100772613
+ },
+ {
+ "id": 3068173057591429
+ },
+ {
+ "id": 3068173057542277
+ },
+ {
+ "id": 3068172411242629
+ },
+ {
+ "id": 3068172411193477
+ },
+ {
+ "id": 3068165923555589
+ },
+ {
+ "id": 3068144683387141
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 551,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 551,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 117,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:30:53.629320+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18387,
+ "diff": -18386
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 465,
+ "diff": -465
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 465,
+ "ods": 465,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 9264.7,
+ "ods_sum": 9264.7,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 21930.18,
+ "ods_sum": 21930.18,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 61454.19,
+ "ods_sum": 61454.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 28610.12,
+ "ods_sum": 28610.12,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18387,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 329604.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 138,
+ "ods": 138,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 40013.33,
+ "ods_sum": 40013.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 331,
+ "ods": 331,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 22654.0,
+ "ods_sum": 22654.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 21930.18,
+ "ods_sum": 21930.18,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11428,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 330,
+ "ods": 330,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 22452.0,
+ "ods_sum": 22452.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16981,
+ "diff": -4
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 524,
+ "ods": 524,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 59984.0,
+ "ods_sum": 59984.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18840
+ },
+ "generated_at": "2026-01-26T21:30:58.013020+08:00"
+ }
+ ],
+ "total_missing": 1060,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:30:58.013039+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_220521.json b/etl_billiards/reports/data_integrity_history_20260126_220521.json
new file mode 100644
index 0000000..bb42b9e
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_220521.json
@@ -0,0 +1,12264 @@
+{
+ "mode": "history",
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17012,
+ "records_with_pk": 17012,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8179,
+ "records_with_pk": 8179,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:41:09.504385+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19755
+ },
+ "generated_at": "2026-01-26T21:41:13.229803+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17012,
+ "records_with_pk": 17012,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8179,
+ "records_with_pk": 8179,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:44:08.151349+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -22096
+ },
+ "generated_at": "2026-01-26T21:44:12.218788+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8179,
+ "records_with_pk": 8179,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:46:58.872006+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19773
+ },
+ "generated_at": "2026-01-26T21:47:07.017111+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8179,
+ "records_with_pk": 8179,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:49:28.375378+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21333
+ },
+ "generated_at": "2026-01-26T21:49:32.142106+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8179,
+ "records_with_pk": 8179,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 6,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:52:24.403264+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21845
+ },
+ "generated_at": "2026-01-26T21:52:28.247932+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11800,
+ "records_with_pk": 11800,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8180,
+ "records_with_pk": 8180,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068238205438213
+ },
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 7,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:55:28.924920+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21988
+ },
+ "generated_at": "2026-01-26T21:55:32.591657+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9971,
+ "records_with_pk": 9971,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068238204815621
+ },
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11801,
+ "records_with_pk": 11801,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068238202161413
+ },
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8181,
+ "records_with_pk": 8181,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068240798615749
+ },
+ {
+ "id": 3068238205438213
+ },
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 10,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T21:58:00.135945+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19208
+ },
+ "generated_at": "2026-01-26T21:58:04.110876+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9972,
+ "records_with_pk": 9972,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068240797878469
+ },
+ {
+ "id": 3068238204815621
+ },
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11801,
+ "records_with_pk": 11801,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068240795322565
+ },
+ {
+ "id": 3068238202161413
+ },
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8182,
+ "records_with_pk": 8182,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068244055787781
+ },
+ {
+ "id": 3068240798615749
+ },
+ {
+ "id": 3068238205438213
+ },
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:00:28.049208+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19181
+ },
+ "generated_at": "2026-01-26T22:00:31.811348+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9973,
+ "records_with_pk": 9973,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068244055197957
+ },
+ {
+ "id": 3068240797878469
+ },
+ {
+ "id": 3068238204815621
+ },
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11803,
+ "records_with_pk": 11803,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068244052953349
+ },
+ {
+ "id": 3068240795322565
+ },
+ {
+ "id": 3068238202161413
+ },
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8183,
+ "records_with_pk": 8183,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068245704181957
+ },
+ {
+ "id": 3068244055787781
+ },
+ {
+ "id": 3068240798615749
+ },
+ {
+ "id": 3068238205438213
+ },
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:02:54.079041+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19285
+ },
+ "generated_at": "2026-01-26T22:02:57.848303+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T22:34:55.893505+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 602,
+ "records_with_pk": 602,
+ "missing": 33,
+ "missing_samples": [
+ {
+ "id": 3068247587326149
+ },
+ {
+ "id": 3068245677574277
+ },
+ {
+ "id": 3068244005472389
+ },
+ {
+ "id": 3068240723380549
+ },
+ {
+ "id": 3068238181681285
+ },
+ {
+ "id": 3068222416193797
+ },
+ {
+ "id": 3068219408025861
+ },
+ {
+ "id": 3068210285201669
+ },
+ {
+ "id": 3068205015746821
+ },
+ {
+ "id": 3068204058937477
+ },
+ {
+ "id": 3068195036170501
+ },
+ {
+ "id": 3068191206459653
+ },
+ {
+ "id": 3068189824059589
+ },
+ {
+ "id": 3068187415611653
+ },
+ {
+ "id": 3068178355669125
+ },
+ {
+ "id": 3068178301192325
+ },
+ {
+ "id": 3068176777808133
+ },
+ {
+ "id": 3068173758433541
+ },
+ {
+ "id": 3068172788353285
+ },
+ {
+ "id": 3068172286822597
+ },
+ {
+ "id": 3068165730896197
+ },
+ {
+ "id": 3068161172441285
+ },
+ {
+ "id": 3068156440938821
+ },
+ {
+ "id": 3068147068373253
+ },
+ {
+ "id": 3068144643229829
+ },
+ {
+ "id": 3068137701460101
+ },
+ {
+ "id": 3068137475737733
+ },
+ {
+ "id": 3068136505919813
+ },
+ {
+ "id": 3068116726745285
+ },
+ {
+ "id": 3068116674398469
+ },
+ {
+ "id": 3068111450900741
+ },
+ {
+ "id": 3068092211972229
+ },
+ {
+ "id": 3068052938459333
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9975,
+ "records_with_pk": 9975,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068247602841925
+ },
+ {
+ "id": 3068245703362757
+ },
+ {
+ "id": 3068244055197957
+ },
+ {
+ "id": 3068240797878469
+ },
+ {
+ "id": 3068238204815621
+ },
+ {
+ "id": 3068222447274181
+ },
+ {
+ "id": 3068219466008773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 163,
+ "records_with_pk": 163,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068195099363589
+ },
+ {
+ "id": 3068173056575621
+ },
+ {
+ "id": 3068173056116869
+ },
+ {
+ "id": 3068173055641733
+ },
+ {
+ "id": 3068172409686149
+ },
+ {
+ "id": 3068165922752773
+ },
+ {
+ "id": 3068161263503493
+ },
+ {
+ "id": 3068156522088773
+ },
+ {
+ "id": 3068137884190981
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11804,
+ "records_with_pk": 11804,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068247600548165
+ },
+ {
+ "id": 3068245698775237
+ },
+ {
+ "id": 3068244052953349
+ },
+ {
+ "id": 3068240795322565
+ },
+ {
+ "id": 3068238202161413
+ },
+ {
+ "id": 3068222444570821
+ },
+ {
+ "id": 3068219463567557
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17013,
+ "records_with_pk": 17013,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068229355096261
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068193226131717
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8184,
+ "records_with_pk": 8184,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068247606249797
+ },
+ {
+ "id": 3068245704181957
+ },
+ {
+ "id": 3068244055787781
+ },
+ {
+ "id": 3068240798615749
+ },
+ {
+ "id": 3068238205438213
+ },
+ {
+ "id": 3068222448126149
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1034,
+ "records_with_pk": 1034,
+ "missing": 36,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068245858044101
+ },
+ {
+ "sitegoodsstockid": 3068238403602693
+ },
+ {
+ "sitegoodsstockid": 3068238398638405
+ },
+ {
+ "sitegoodsstockid": 3068230906775685
+ },
+ {
+ "sitegoodsstockid": 3068230907365509
+ },
+ {
+ "sitegoodsstockid": 3068222972643653
+ },
+ {
+ "sitegoodsstockid": 3068212484425861
+ },
+ {
+ "sitegoodsstockid": 3068212393527493
+ },
+ {
+ "sitegoodsstockid": 3068211882658053
+ },
+ {
+ "sitegoodsstockid": 3068185293736197
+ },
+ {
+ "sitegoodsstockid": 3068173817415941
+ },
+ {
+ "sitegoodsstockid": 3068166835570885
+ },
+ {
+ "sitegoodsstockid": 3068165128079621
+ },
+ {
+ "sitegoodsstockid": 3068159660001413
+ },
+ {
+ "sitegoodsstockid": 3068158269720838
+ },
+ {
+ "sitegoodsstockid": 3068158132488389
+ },
+ {
+ "sitegoodsstockid": 3068143580711045
+ },
+ {
+ "sitegoodsstockid": 3068142510311621
+ },
+ {
+ "sitegoodsstockid": 3068142511032517
+ },
+ {
+ "sitegoodsstockid": 3068135950321861
+ },
+ {
+ "sitegoodsstockid": 3068135950846149
+ },
+ {
+ "sitegoodsstockid": 3068135276693829
+ },
+ {
+ "sitegoodsstockid": 3068135277218117
+ },
+ {
+ "sitegoodsstockid": 3068132803037509
+ },
+ {
+ "sitegoodsstockid": 3068126246095109
+ },
+ {
+ "sitegoodsstockid": 3068125658253573
+ },
+ {
+ "sitegoodsstockid": 3068096166971717
+ },
+ {
+ "sitegoodsstockid": 3068096166529349
+ },
+ {
+ "sitegoodsstockid": 3068090895648965
+ },
+ {
+ "sitegoodsstockid": 3068058833127621
+ },
+ {
+ "sitegoodsstockid": 3068045209585989
+ },
+ {
+ "sitegoodsstockid": 3068045210061125
+ },
+ {
+ "sitegoodsstockid": 3068033580435653
+ },
+ {
+ "sitegoodsstockid": 3068033136544069
+ },
+ {
+ "sitegoodsstockid": 3068032978126981
+ },
+ {
+ "sitegoodsstockid": 3068032978634885
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 616,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 616,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 100,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:05:18.017923+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18415,
+ "diff": -18414
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 514,
+ "diff": -514
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 503,
+ "ods": 514,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 10412.32,
+ "ods_sum": 10480.32,
+ "diff": -68.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 23440.18,
+ "ods_sum": 24162.18,
+ "diff": -722.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66552.38,
+ "ods_sum": 67554.66,
+ "diff": -1002.2799999999988
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 31050.69,
+ "ods_sum": 31262.97,
+ "diff": -212.28000000000247
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18415,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 150,
+ "ods": 150,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 45010.31,
+ "ods_sum": 45010.31,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4753,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 349,
+ "ods": 364,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 23828.0,
+ "ods_sum": 24982.0,
+ "diff": -1154.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 23104.18,
+ "ods_sum": 24162.18,
+ "diff": -1058.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11445,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 355,
+ "ods": 375,
+ "diff": -20
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 24424.0,
+ "ods_sum": 25974.0,
+ "diff": -1550.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17012,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 567,
+ "ods": 578,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 66836.0,
+ "ods_sum": 67261.0,
+ "diff": -425.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19080
+ },
+ "generated_at": "2026-01-26T22:05:21.737201+08:00"
+ }
+ ],
+ "total_missing": 174,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:05:21.737221+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_225143.json b/etl_billiards/reports/data_integrity_history_20260126_225143.json
new file mode 100644
index 0000000..1c20168
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_225143.json
@@ -0,0 +1,12704 @@
+{
+ "mode": "history",
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9981,
+ "records_with_pk": 9981,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11811,
+ "records_with_pk": 11811,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17016,
+ "records_with_pk": 17016,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8188,
+ "records_with_pk": 8188,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 16,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:25:25.984117+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19805
+ },
+ "generated_at": "2026-01-26T22:25:35.502207+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9981,
+ "records_with_pk": 9981,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11811,
+ "records_with_pk": 11811,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17019,
+ "records_with_pk": 17019,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8188,
+ "records_with_pk": 8188,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 18,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:28:38.135178+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -22146
+ },
+ "generated_at": "2026-01-26T22:28:47.377846+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9981,
+ "records_with_pk": 9981,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11811,
+ "records_with_pk": 11811,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17020,
+ "records_with_pk": 17020,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8189,
+ "records_with_pk": 8189,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 20,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:31:48.060101+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19823
+ },
+ "generated_at": "2026-01-26T22:31:57.213589+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9982,
+ "records_with_pk": 9982,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11812,
+ "records_with_pk": 11812,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17020,
+ "records_with_pk": 17020,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8189,
+ "records_with_pk": 8189,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 23,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:34:28.080847+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21383
+ },
+ "generated_at": "2026-01-26T22:34:37.417709+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9982,
+ "records_with_pk": 9982,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11812,
+ "records_with_pk": 11812,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17020,
+ "records_with_pk": 17020,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8189,
+ "records_with_pk": 8189,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 23,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:37:41.485975+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21895
+ },
+ "generated_at": "2026-01-26T22:37:50.690900+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9982,
+ "records_with_pk": 9982,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11812,
+ "records_with_pk": 11812,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17020,
+ "records_with_pk": 17020,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8189,
+ "records_with_pk": 8189,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 23,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:40:56.369171+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -22038
+ },
+ "generated_at": "2026-01-26T22:41:05.591623+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9982,
+ "records_with_pk": 9982,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11812,
+ "records_with_pk": 11812,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17021,
+ "records_with_pk": 17021,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068283901102341
+ },
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8190,
+ "records_with_pk": 8190,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068286601333061
+ },
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 25,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:43:39.052543+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19258
+ },
+ "generated_at": "2026-01-26T22:43:48.261023+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9984,
+ "records_with_pk": 9984,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068287557994693
+ },
+ {
+ "id": 3068286600710469
+ },
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11815,
+ "records_with_pk": 11815,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068287555635397
+ },
+ {
+ "id": 3068287473535237
+ },
+ {
+ "id": 3068286598154565
+ },
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17021,
+ "records_with_pk": 17021,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068283901102341
+ },
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8192,
+ "records_with_pk": 8192,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068287558666437
+ },
+ {
+ "id": 3068286601333061
+ },
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 31,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:46:19.589435+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19231
+ },
+ "generated_at": "2026-01-26T22:46:28.856495+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9987,
+ "records_with_pk": 9987,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068290500462853
+ },
+ {
+ "id": 3068290141849733
+ },
+ {
+ "id": 3068290064632005
+ },
+ {
+ "id": 3068287557994693
+ },
+ {
+ "id": 3068286600710469
+ },
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11818,
+ "records_with_pk": 11818,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068290498054405
+ },
+ {
+ "id": 3068290139605125
+ },
+ {
+ "id": 3068290062371013
+ },
+ {
+ "id": 3068287555635397
+ },
+ {
+ "id": 3068287473535237
+ },
+ {
+ "id": 3068286598154565
+ },
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17021,
+ "records_with_pk": 17021,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3068283901102341
+ },
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8194,
+ "records_with_pk": 8194,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068290501101829
+ },
+ {
+ "id": 3068290142537861
+ },
+ {
+ "id": 3068290065369285
+ },
+ {
+ "id": 3068287558666437
+ },
+ {
+ "id": 3068286601333061
+ },
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:48:56.922377+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19335
+ },
+ "generated_at": "2026-01-26T22:49:06.110845+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T22:34:55.893505+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 610,
+ "records_with_pk": 610,
+ "missing": 30,
+ "missing_samples": [
+ {
+ "id": 3068274759174405
+ },
+ {
+ "id": 3068266628860165
+ },
+ {
+ "id": 3068265453193477
+ },
+ {
+ "id": 3068260351953093
+ },
+ {
+ "id": 3068260196206917
+ },
+ {
+ "id": 3068253977921861
+ },
+ {
+ "id": 3068250782402757
+ },
+ {
+ "id": 3068248546969925
+ },
+ {
+ "id": 3068247587326149
+ },
+ {
+ "id": 3068245677574277
+ },
+ {
+ "id": 3068244005472389
+ },
+ {
+ "id": 3068240723380549
+ },
+ {
+ "id": 3068238181681285
+ },
+ {
+ "id": 3068222416193797
+ },
+ {
+ "id": 3068219408025861
+ },
+ {
+ "id": 3068210285201669
+ },
+ {
+ "id": 3068205015746821
+ },
+ {
+ "id": 3068204058937477
+ },
+ {
+ "id": 3068195036170501
+ },
+ {
+ "id": 3068191206459653
+ },
+ {
+ "id": 3068189824059589
+ },
+ {
+ "id": 3068187415611653
+ },
+ {
+ "id": 3068178355669125
+ },
+ {
+ "id": 3068178301192325
+ },
+ {
+ "id": 3068176777808133
+ },
+ {
+ "id": 3068173758433541
+ },
+ {
+ "id": 3068172788353285
+ },
+ {
+ "id": 3068172286822597
+ },
+ {
+ "id": 3068165730896197
+ },
+ {
+ "id": 3068161172441285
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9987,
+ "records_with_pk": 9987,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068290500462853
+ },
+ {
+ "id": 3068290141849733
+ },
+ {
+ "id": 3068290064632005
+ },
+ {
+ "id": 3068287557994693
+ },
+ {
+ "id": 3068286600710469
+ },
+ {
+ "id": 3068274787764421
+ },
+ {
+ "id": 3068266646079813
+ },
+ {
+ "id": 3068265469315205
+ },
+ {
+ "id": 3068260367649093
+ },
+ {
+ "id": 3068260212164869
+ },
+ {
+ "id": 3068254185769285
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 164,
+ "records_with_pk": 164,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068248572709125
+ },
+ {
+ "id": 3068195099363589
+ },
+ {
+ "id": 3068173056575621
+ },
+ {
+ "id": 3068173056116869
+ },
+ {
+ "id": 3068173055641733
+ },
+ {
+ "id": 3068172409686149
+ },
+ {
+ "id": 3068165922752773
+ },
+ {
+ "id": 3068161263503493
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11818,
+ "records_with_pk": 11818,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068290498054405
+ },
+ {
+ "id": 3068290139605125
+ },
+ {
+ "id": 3068290062371013
+ },
+ {
+ "id": 3068287555635397
+ },
+ {
+ "id": 3068287473535237
+ },
+ {
+ "id": 3068286598154565
+ },
+ {
+ "id": 3068274782423237
+ },
+ {
+ "id": 3068266643687749
+ },
+ {
+ "id": 3068265466955909
+ },
+ {
+ "id": 3068260365519173
+ },
+ {
+ "id": 3068260209543429
+ },
+ {
+ "id": 3068254182918469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17022,
+ "records_with_pk": 17022,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068292445669573
+ },
+ {
+ "id": 3068283901102341
+ },
+ {
+ "id": 3068274381588741
+ },
+ {
+ "id": 3068271374993733
+ },
+ {
+ "id": 3068269539461381
+ },
+ {
+ "id": 3068268636555397
+ },
+ {
+ "id": 3068261508647045
+ },
+ {
+ "id": 3068254532045125
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068193226131717
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8194,
+ "records_with_pk": 8194,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068290501101829
+ },
+ {
+ "id": 3068290142537861
+ },
+ {
+ "id": 3068290065369285
+ },
+ {
+ "id": 3068287558666437
+ },
+ {
+ "id": 3068286601333061
+ },
+ {
+ "id": 3068274788403397
+ },
+ {
+ "id": 3068266646669637
+ },
+ {
+ "id": 3068265469970565
+ },
+ {
+ "id": 3068260368353605
+ },
+ {
+ "id": 3068260212705541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1042,
+ "records_with_pk": 1042,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068274887936325
+ },
+ {
+ "sitegoodsstockid": 3068274743986437
+ },
+ {
+ "sitegoodsstockid": 3068266527918213
+ },
+ {
+ "sitegoodsstockid": 3068264303184005
+ },
+ {
+ "sitegoodsstockid": 3068264302692485
+ },
+ {
+ "sitegoodsstockid": 3068260102326469
+ },
+ {
+ "sitegoodsstockid": 3068260102817989
+ },
+ {
+ "sitegoodsstockid": 3068251627522245
+ },
+ {
+ "sitegoodsstockid": 3068245858044101
+ },
+ {
+ "sitegoodsstockid": 3068238403602693
+ },
+ {
+ "sitegoodsstockid": 3068238398638405
+ },
+ {
+ "sitegoodsstockid": 3068230906775685
+ },
+ {
+ "sitegoodsstockid": 3068230907365509
+ },
+ {
+ "sitegoodsstockid": 3068222972643653
+ },
+ {
+ "sitegoodsstockid": 3068212484425861
+ },
+ {
+ "sitegoodsstockid": 3068212393527493
+ },
+ {
+ "sitegoodsstockid": 3068211882658053
+ },
+ {
+ "sitegoodsstockid": 3068185293736197
+ },
+ {
+ "sitegoodsstockid": 3068173817415941
+ },
+ {
+ "sitegoodsstockid": 3068166835570885
+ },
+ {
+ "sitegoodsstockid": 3068165128079621
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 623,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 623,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 101,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:51:34.507237+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18423,
+ "diff": -18422
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 514,
+ "diff": -514
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 503,
+ "ods": 514,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 10412.32,
+ "ods_sum": 10480.32,
+ "diff": -68.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 23440.18,
+ "ods_sum": 24162.18,
+ "diff": -722.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66552.38,
+ "ods_sum": 67554.66,
+ "diff": -1002.2799999999988
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 31050.69,
+ "ods_sum": 31262.97,
+ "diff": -212.28000000000247
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18423,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 150,
+ "ods": 152,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 45010.31,
+ "ods_sum": 45965.85,
+ "diff": -955.5400000000009
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 349,
+ "ods": 364,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 23828.0,
+ "ods_sum": 24982.0,
+ "diff": -1154.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 23104.18,
+ "ods_sum": 24162.18,
+ "diff": -1058.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11451,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 355,
+ "ods": 375,
+ "diff": -20
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 24424.0,
+ "ods_sum": 25974.0,
+ "diff": -1550.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17014,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 567,
+ "ods": 578,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 66836.0,
+ "ods_sum": 67261.0,
+ "diff": -425.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19132
+ },
+ "generated_at": "2026-01-26T22:51:43.867285+08:00"
+ }
+ ],
+ "total_missing": 320,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T22:51:43.867306+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260126_234946.json b/etl_billiards/reports/data_integrity_history_20260126_234946.json
new file mode 100644
index 0000000..a748045
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260126_234946.json
@@ -0,0 +1,12989 @@
+{
+ "mode": "history",
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2025-08-01T00:00:00+08:00",
+ "label": "month_2025-07-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-06-30T22:00:00+08:00",
+ "end": "2025-08-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1798,
+ "records_with_pk": 1798,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 11,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9992,
+ "records_with_pk": 9992,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 355,
+ "records_with_pk": 355,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11823,
+ "records_with_pk": 11823,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17026,
+ "records_with_pk": 17026,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 44,
+ "records_with_pk": 44,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8202,
+ "records_with_pk": 8202,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2578,
+ "records_with_pk": 2578,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 15,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1867,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 12,
+ "skipped_missing_pk": 1867,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 22,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:25:23.126672+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1246,
+ "diff": -1246
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 23,
+ "ods": 23,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 466,
+ "ods": 466,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 751,
+ "ods": 751,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 149,
+ "ods": 149,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 14,
+ "ods": 14,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1246,
+ "ods": 1246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 18607.65,
+ "ods_sum": 18607.65,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 68759.8,
+ "ods_sum": 68759.8,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133842.45,
+ "ods_sum": 133842.45,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 10234.83,
+ "ods_sum": 10234.83,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 46883.63,
+ "ods_sum": 46883.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1575,
+ "ods": 1575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 14.25,
+ "ods_sum": 14.25,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31186.8,
+ "ods_sum": 31186.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 29160.8,
+ "ods_sum": 29160.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 351,
+ "ods": 351,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1261.59,
+ "ods_sum": 1261.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 113232.99,
+ "ods_sum": 113232.99,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1007,
+ "ods": 1007,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 72348.0,
+ "ods_sum": 72348.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1833,
+ "ods": 1833,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 178060.0,
+ "ods_sum": 178060.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19845
+ },
+ "generated_at": "2026-01-26T23:25:28.275880+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-08-01T00:00:00+08:00",
+ "end": "2025-09-01T00:00:00+08:00",
+ "label": "month_2025-08-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-07-31T22:00:00+08:00",
+ "end": "2025-09-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4653,
+ "records_with_pk": 4653,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9993,
+ "records_with_pk": 9993,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 867,
+ "records_with_pk": 867,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11824,
+ "records_with_pk": 11824,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 96,
+ "records_with_pk": 96,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8202,
+ "records_with_pk": 8202,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5271,
+ "records_with_pk": 5271,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 28,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4817,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 26,
+ "skipped_missing_pk": 4817,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 25,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:28:29.582357+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3587,
+ "diff": -3587
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 18,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3587,
+ "ods": 3587,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 54919.33,
+ "ods_sum": 54919.33,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 186359.95,
+ "ods_sum": 186359.95,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 383097.96,
+ "ods_sum": 383097.96,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 44840.88,
+ "ods_sum": 44840.88,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 145513.13,
+ "ods_sum": 145513.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4305,
+ "ods": 4305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 47.45,
+ "ods_sum": 47.45,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 87523.4,
+ "ods_sum": 87523.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 83759.0,
+ "ods_sum": 83759.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 859,
+ "ods": 859,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1874.75,
+ "ods_sum": 1874.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 268501.57,
+ "ods_sum": 268501.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2850,
+ "ods": 2850,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 189960.0,
+ "ods_sum": 189960.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4763,
+ "ods": 4763,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 381598.0,
+ "ods_sum": 381598.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -22186
+ },
+ "generated_at": "2026-01-26T23:28:35.555328+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-09-01T00:00:00+08:00",
+ "end": "2025-10-01T00:00:00+08:00",
+ "label": "month_2025-09-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-08-31T22:00:00+08:00",
+ "end": "2025-10-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3738,
+ "records_with_pk": 3738,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9996,
+ "records_with_pk": 9996,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 655,
+ "records_with_pk": 655,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11827,
+ "records_with_pk": 11827,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 54,
+ "records_with_pk": 54,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4853,
+ "records_with_pk": 4853,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3828,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 3828,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 34,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:31:28.553534+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1264,
+ "diff": -1264
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1264,
+ "ods": 1264,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11020.51,
+ "ods_sum": 11020.51,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 73893.75,
+ "ods_sum": 73893.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 137203.92,
+ "ods_sum": 137203.92,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 15685.02,
+ "ods_sum": 15685.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52340.33,
+ "ods_sum": 52340.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1449,
+ "ods": 1449,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1.41,
+ "ods_sum": 1.41,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24706.9,
+ "ods_sum": 24706.9,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 23874.4,
+ "ods_sum": 23874.4,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 654,
+ "ods": 654,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 781.44,
+ "ods_sum": 781.44,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 192541.75,
+ "ods_sum": 192541.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1173,
+ "ods": 1173,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 75824.0,
+ "ods_sum": 75824.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 73843.08,
+ "ods_sum": 73843.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2849,
+ "ods": 2849,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 184722.0,
+ "ods_sum": 184722.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1544,
+ "ods": 1544,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 108880.0,
+ "ods_sum": 108880.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -1011.0,
+ "ods_sum": -1011.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19863
+ },
+ "generated_at": "2026-01-26T23:31:35.401181+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-10-01T00:00:00+08:00",
+ "end": "2025-11-01T00:00:00+08:00",
+ "label": "month_2025-10-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-09-30T22:00:00+08:00",
+ "end": "2025-11-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 607,
+ "records_with_pk": 607,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9996,
+ "records_with_pk": 9996,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11827,
+ "records_with_pk": 11827,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 997,
+ "records_with_pk": 997,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 619,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 619,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 34,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:34:00.922320+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2824,
+ "diff": -2824
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 21,
+ "ods": 21,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2824,
+ "ods": 2824,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 40394.85,
+ "ods_sum": 40394.85,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 310789.49,
+ "ods_sum": 310789.49,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33315.15,
+ "ods_sum": 33315.15,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 116393.37,
+ "ods_sum": 116393.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3475,
+ "ods": 3475,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1319.49,
+ "ods_sum": 1319.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66216.8,
+ "ods_sum": 66216.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 64234.0,
+ "ods_sum": 64234.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 573,
+ "ods": 573,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 2143.56,
+ "ods_sum": 2143.56,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 172536.78,
+ "ods_sum": 172536.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2490,
+ "ods": 2490,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160988.0,
+ "ods_sum": 160988.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 154001.27,
+ "ods_sum": 154001.27,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2489,
+ "ods": 2489,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 160076.0,
+ "ods_sum": 160076.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3616,
+ "ods": 3616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 286088.0,
+ "ods_sum": 286088.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -47020.0,
+ "ods_sum": -47020.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21423
+ },
+ "generated_at": "2026-01-26T23:34:06.630898+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-11-01T00:00:00+08:00",
+ "end": "2025-12-01T00:00:00+08:00",
+ "label": "month_2025-11-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-10-31T22:00:00+08:00",
+ "end": "2025-12-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3927,
+ "records_with_pk": 3927,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9996,
+ "records_with_pk": 9996,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 890,
+ "records_with_pk": 890,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12,
+ "records_with_pk": 12,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11827,
+ "records_with_pk": 11827,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 80,
+ "records_with_pk": 80,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5561,
+ "records_with_pk": 5561,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4052,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 22,
+ "skipped_missing_pk": 4052,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 34,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:36:58.962277+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3336,
+ "diff": -3336
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 80,
+ "ods": 80,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3336,
+ "ods": 3336,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71642.8,
+ "ods_sum": 71642.8,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 394705.62,
+ "ods_sum": 394705.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 33307.25,
+ "ods_sum": 33307.25,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 156623.79,
+ "ods_sum": 156623.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4134,
+ "ods": 4134,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 1544.05,
+ "ods_sum": 1544.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 98139.8,
+ "ods_sum": 98139.8,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 87610.8,
+ "ods_sum": 87610.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 884,
+ "ods": 884,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 1437.75,
+ "ods_sum": 1437.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 281102.62,
+ "ods_sum": 281102.62,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2838,
+ "ods": 2838,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 172860.0,
+ "ods_sum": 172860.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 166439.03,
+ "ods_sum": 166439.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2843,
+ "ods": 2843,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 173800.0,
+ "ods_sum": 173800.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3999,
+ "ods": 3999,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 457185.0,
+ "ods_sum": 457185.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -16567.0,
+ "ods_sum": -16567.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -21935
+ },
+ "generated_at": "2026-01-26T23:37:04.627972+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2025-12-01T00:00:00+08:00",
+ "end": "2026-01-01T00:00:00+08:00",
+ "label": "month_2025-12-01",
+ "granularity": "month"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-11-30T22:00:00+08:00",
+ "end": "2026-01-01T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 31,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 207,
+ "records_with_pk": 207,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4044,
+ "records_with_pk": 4044,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9997,
+ "records_with_pk": 9997,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068338353047749
+ },
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 984,
+ "records_with_pk": 984,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 35,
+ "records_with_pk": 35,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11828,
+ "records_with_pk": 11828,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068338350475461
+ },
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8205,
+ "records_with_pk": 8205,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5490,
+ "records_with_pk": 5490,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 30,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4151,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 23,
+ "skipped_missing_pk": 4151,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 36,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:39:55.805472+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3479,
+ "diff": -3479
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 5,
+ "ods": 5,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 6,
+ "ods": 6,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 12,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3479,
+ "ods": 3479,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 71445.57,
+ "ods_sum": 71445.57,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 432220.76,
+ "ods_sum": 432220.76,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 34544.63,
+ "ods_sum": 34544.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 189974.44,
+ "ods_sum": 189974.44,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2625,
+ "ods": 2625,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 190.1,
+ "ods_sum": 190.1,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 65814.4,
+ "ods_sum": 65814.4,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 63275.9,
+ "ods_sum": 63275.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 975,
+ "ods": 975,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 3190.05,
+ "ods_sum": 3190.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 322183.69,
+ "ods_sum": 322183.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2816,
+ "ods": 2816,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 179652.0,
+ "ods_sum": 179652.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 170800.75,
+ "ods_sum": 170800.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2827,
+ "ods": 2827,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 180232.0,
+ "ods_sum": 180232.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 4118,
+ "ods": 4118,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 472999.0,
+ "ods_sum": 472999.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 13,
+ "ods": 13,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -4314.0,
+ "ods_sum": -4314.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -22078
+ },
+ "generated_at": "2026-01-26T23:40:01.540276+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-08T00:00:00+08:00",
+ "label": "week_2026-01-01",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2025-12-31T22:00:00+08:00",
+ "end": "2026-01-08T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9998,
+ "records_with_pk": 9998,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068342767175813
+ },
+ {
+ "id": 3068338353047749
+ },
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 167,
+ "records_with_pk": 167,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11829,
+ "records_with_pk": 11829,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068342764128389
+ },
+ {
+ "id": 3068338350475461
+ },
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8207,
+ "records_with_pk": 8207,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068342768208005
+ },
+ {
+ "id": 3068342768208006
+ },
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 880,
+ "records_with_pk": 880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 851,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 851,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:42:26.585247+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 699,
+ "diff": -699
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 699,
+ "ods": 699,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 8896.03,
+ "ods_sum": 8896.03,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 74693.62,
+ "ods_sum": 74693.62,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6587.39,
+ "ods_sum": 6587.39,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30138.48,
+ "ods_sum": 30138.48,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 157,
+ "ods": 157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 46522.68,
+ "ods_sum": 46522.68,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 569,
+ "ods": 569,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37392.0,
+ "ods_sum": 37392.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35659.11,
+ "ods_sum": 35659.11,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 566,
+ "ods": 566,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37228.0,
+ "ods_sum": 37228.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 823,
+ "ods": 823,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 78730.0,
+ "ods_sum": 78730.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19298
+ },
+ "generated_at": "2026-01-26T23:42:31.972383+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-08T00:00:00+08:00",
+ "end": "2026-01-15T00:00:00+08:00",
+ "label": "week_2026-01-08",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-07T22:00:00+08:00",
+ "end": "2026-01-15T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 790,
+ "records_with_pk": 790,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9998,
+ "records_with_pk": 9998,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068342767175813
+ },
+ {
+ "id": 3068338353047749
+ },
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 195,
+ "records_with_pk": 195,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 22,
+ "records_with_pk": 22,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11829,
+ "records_with_pk": 11829,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068342764128389
+ },
+ {
+ "id": 3068338350475461
+ },
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17027,
+ "records_with_pk": 17027,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8207,
+ "records_with_pk": 8207,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068342768208005
+ },
+ {
+ "id": 3068342768208006
+ },
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1241,
+ "records_with_pk": 1241,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 814,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 814,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:44:48.226506+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 672,
+ "diff": -672
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 672,
+ "ods": 672,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16159.12,
+ "ods_sum": 16159.12,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 82416.19,
+ "ods_sum": 82416.19,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 6098.02,
+ "ods_sum": 6098.02,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 30731.98,
+ "ods_sum": 30731.98,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 188,
+ "ods": 188,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 54584.19,
+ "ods_sum": 54584.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 572,
+ "ods": 572,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37214.0,
+ "ods_sum": 37214.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 35525.09,
+ "ods_sum": 35525.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 575,
+ "ods": 575,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 37262.0,
+ "ods_sum": 37262.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 790,
+ "ods": 790,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 86381.0,
+ "ods_sum": 86381.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -39.0,
+ "ods_sum": -39.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19271
+ },
+ "generated_at": "2026-01-26T23:44:55.680428+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-15T00:00:00+08:00",
+ "end": "2026-01-22T00:00:00+08:00",
+ "label": "week_2026-01-15",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-14T22:00:00+08:00",
+ "end": "2026-01-22T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 7,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 899,
+ "records_with_pk": 899,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9999,
+ "records_with_pk": 9999,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068347773946117
+ },
+ {
+ "id": 3068342767175813
+ },
+ {
+ "id": 3068338353047749
+ },
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 216,
+ "records_with_pk": 216,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11830,
+ "records_with_pk": 11830,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068347769456901
+ },
+ {
+ "id": 3068342764128389
+ },
+ {
+ "id": 3068338350475461
+ },
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17028,
+ "records_with_pk": 17028,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068347514390789
+ },
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8209,
+ "records_with_pk": 8209,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068347774716165
+ },
+ {
+ "id": 3068347774716166
+ },
+ {
+ "id": 3068342768208005
+ },
+ {
+ "id": 3068342768208006
+ },
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1181,
+ "records_with_pk": 1181,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 932,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 932,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 45,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:47:14.385605+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 776,
+ "diff": -776
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 4,
+ "ods": 4,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 7,
+ "ods": 7,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 776,
+ "ods": 776,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 16959.34,
+ "ods_sum": 16959.34,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93110.51,
+ "ods_sum": 93110.51,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 5009.13,
+ "ods_sum": 5009.13,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 40591.34,
+ "ods_sum": 40591.34,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 212,
+ "ods": 212,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 191.21,
+ "ods_sum": 191.21,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 70610.77,
+ "ods_sum": 70610.77,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 613,
+ "ods": 613,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40100.0,
+ "ods_sum": 40100.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 38520.64,
+ "ods_sum": 38520.64,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 616,
+ "ods": 616,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 40456.0,
+ "ods_sum": 40456.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 896,
+ "ods": 896,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 123718.0,
+ "ods_sum": 123718.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -34.0,
+ "ods_sum": -34.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19375
+ },
+ "generated_at": "2026-01-26T23:47:19.616551+08:00"
+ },
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-22T00:00:00+08:00",
+ "end": "2026-01-26T20:34:55.893505+08:00",
+ "label": "week_2026-01-22",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-21T22:00:00+08:00",
+ "end": "2026-01-26T22:34:55.893505+08:00",
+ "cutoff": null,
+ "window_days": 4,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 610,
+ "records_with_pk": 610,
+ "missing": 30,
+ "missing_samples": [
+ {
+ "id": 3068274759174405
+ },
+ {
+ "id": 3068266628860165
+ },
+ {
+ "id": 3068265453193477
+ },
+ {
+ "id": 3068260351953093
+ },
+ {
+ "id": 3068260196206917
+ },
+ {
+ "id": 3068253977921861
+ },
+ {
+ "id": 3068250782402757
+ },
+ {
+ "id": 3068248546969925
+ },
+ {
+ "id": 3068247587326149
+ },
+ {
+ "id": 3068245677574277
+ },
+ {
+ "id": 3068244005472389
+ },
+ {
+ "id": 3068240723380549
+ },
+ {
+ "id": 3068238181681285
+ },
+ {
+ "id": 3068222416193797
+ },
+ {
+ "id": 3068219408025861
+ },
+ {
+ "id": 3068210285201669
+ },
+ {
+ "id": 3068205015746821
+ },
+ {
+ "id": 3068204058937477
+ },
+ {
+ "id": 3068195036170501
+ },
+ {
+ "id": 3068191206459653
+ },
+ {
+ "id": 3068189824059589
+ },
+ {
+ "id": 3068187415611653
+ },
+ {
+ "id": 3068178355669125
+ },
+ {
+ "id": 3068178301192325
+ },
+ {
+ "id": 3068176777808133
+ },
+ {
+ "id": 3068173758433541
+ },
+ {
+ "id": 3068172788353285
+ },
+ {
+ "id": 3068172286822597
+ },
+ {
+ "id": 3068165730896197
+ },
+ {
+ "id": 3068161172441285
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9999,
+ "records_with_pk": 9999,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068347773946117
+ },
+ {
+ "id": 3068342767175813
+ },
+ {
+ "id": 3068338353047749
+ },
+ {
+ "id": 3068331886758085
+ },
+ {
+ "id": 3068331829921989
+ },
+ {
+ "id": 3068331775887493
+ },
+ {
+ "id": 3068327641483397
+ },
+ {
+ "id": 3068325674469573
+ },
+ {
+ "id": 3068325570955525
+ },
+ {
+ "id": 3068320107727109
+ },
+ {
+ "id": 3068303249115461
+ },
+ {
+ "id": 3068302178781381
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 164,
+ "records_with_pk": 164,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3068248572709125
+ },
+ {
+ "id": 3068195099363589
+ },
+ {
+ "id": 3068173056575621
+ },
+ {
+ "id": 3068173056116869
+ },
+ {
+ "id": 3068173055641733
+ },
+ {
+ "id": 3068172409686149
+ },
+ {
+ "id": 3068165922752773
+ },
+ {
+ "id": 3068161263503493
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11830,
+ "records_with_pk": 11830,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068347769456901
+ },
+ {
+ "id": 3068342764128389
+ },
+ {
+ "id": 3068338350475461
+ },
+ {
+ "id": 3068331884513477
+ },
+ {
+ "id": 3068331827660997
+ },
+ {
+ "id": 3068331773233285
+ },
+ {
+ "id": 3068327639173253
+ },
+ {
+ "id": 3068325671520453
+ },
+ {
+ "id": 3068325568678149
+ },
+ {
+ "id": 3068320105253125
+ },
+ {
+ "id": 3068303246281029
+ },
+ {
+ "id": 3068302176618693
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17028,
+ "records_with_pk": 17028,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068347514390789
+ },
+ {
+ "id": 3068327551846725
+ },
+ {
+ "id": 3068319991449861
+ },
+ {
+ "id": 3068303788198214
+ },
+ {
+ "id": 3068303788198213
+ },
+ {
+ "id": 3068303397751109
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2469,
+ "records_with_pk": 2469,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068193226131717
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8209,
+ "records_with_pk": 8209,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "id": 3068347774716165
+ },
+ {
+ "id": 3068347774716166
+ },
+ {
+ "id": 3068342768208005
+ },
+ {
+ "id": 3068342768208006
+ },
+ {
+ "id": 3068331887364293
+ },
+ {
+ "id": 3068331830560965
+ },
+ {
+ "id": 3068331776444549
+ },
+ {
+ "id": 3068327642089605
+ },
+ {
+ "id": 3068325675239621
+ },
+ {
+ "id": 3068325675256005
+ },
+ {
+ "id": 3068325675256006
+ },
+ {
+ "id": 3068325571528965
+ },
+ {
+ "id": 3068320108431621
+ },
+ {
+ "id": 3068320108431622
+ },
+ {
+ "id": 3068302179305669
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1042,
+ "records_with_pk": 1042,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068274887936325
+ },
+ {
+ "sitegoodsstockid": 3068274743986437
+ },
+ {
+ "sitegoodsstockid": 3068266527918213
+ },
+ {
+ "sitegoodsstockid": 3068264303184005
+ },
+ {
+ "sitegoodsstockid": 3068264302692485
+ },
+ {
+ "sitegoodsstockid": 3068260102326469
+ },
+ {
+ "sitegoodsstockid": 3068260102817989
+ },
+ {
+ "sitegoodsstockid": 3068251627522245
+ },
+ {
+ "sitegoodsstockid": 3068245858044101
+ },
+ {
+ "sitegoodsstockid": 3068238403602693
+ },
+ {
+ "sitegoodsstockid": 3068238398638405
+ },
+ {
+ "sitegoodsstockid": 3068230906775685
+ },
+ {
+ "sitegoodsstockid": 3068230907365509
+ },
+ {
+ "sitegoodsstockid": 3068222972643653
+ },
+ {
+ "sitegoodsstockid": 3068212484425861
+ },
+ {
+ "sitegoodsstockid": 3068212393527493
+ },
+ {
+ "sitegoodsstockid": 3068211882658053
+ },
+ {
+ "sitegoodsstockid": 3068185293736197
+ },
+ {
+ "sitegoodsstockid": 3068173817415941
+ },
+ {
+ "sitegoodsstockid": 3068166835570885
+ },
+ {
+ "sitegoodsstockid": 3068165128079621
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 623,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 4,
+ "skipped_missing_pk": 623,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 105,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:49:40.625876+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18434,
+ "diff": -18433
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 514,
+ "diff": -514
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 503,
+ "ods": 514,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 10412.32,
+ "ods_sum": 10480.32,
+ "diff": -68.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 23440.18,
+ "ods_sum": 24162.18,
+ "diff": -722.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 66552.38,
+ "ods_sum": 67554.66,
+ "diff": -1002.2799999999988
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1649.19,
+ "ods_sum": 1649.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 31050.69,
+ "ods_sum": 31262.97,
+ "diff": -212.28000000000247
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18434,
+ "diff": -48
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 150,
+ "ods": 152,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 45010.31,
+ "ods_sum": 45965.85,
+ "diff": -955.5400000000009
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 349,
+ "ods": 364,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 23828.0,
+ "ods_sum": 24982.0,
+ "diff": -1154.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 23104.18,
+ "ods_sum": 24162.18,
+ "diff": -1058.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11461,
+ "diff": -34
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 355,
+ "ods": 375,
+ "diff": -20
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 24424.0,
+ "ods_sum": 25974.0,
+ "diff": -1550.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17022,
+ "diff": -45
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 567,
+ "ods": 578,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 66836.0,
+ "ods_sum": 67261.0,
+ "diff": -425.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19172
+ },
+ "generated_at": "2026-01-26T23:49:46.864454+08:00"
+ }
+ ],
+ "total_missing": 415,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T23:49:46.864479+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260127_024335.json b/etl_billiards/reports/data_integrity_history_20260127_024335.json
new file mode 100644
index 0000000..03c7dc7
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260127_024335.json
@@ -0,0 +1,1690 @@
+{
+ "mode": "history",
+ "start": "2026-01-26T00:00:00+08:00",
+ "end": "2026-01-27T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-26T00:00:00+08:00",
+ "end": "2026-01-27T00:00:00+08:00",
+ "label": "week_2026-01-26",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-25T22:00:00+08:00",
+ "end": "2026-01-27T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 137,
+ "records_with_pk": 137,
+ "missing": 63,
+ "missing_samples": [
+ {
+ "id": 3068478831069509
+ },
+ {
+ "id": 3068478749411461
+ },
+ {
+ "id": 3068449874594117
+ },
+ {
+ "id": 3068439717660805
+ },
+ {
+ "id": 3068425134852421
+ },
+ {
+ "id": 3068420801906885
+ },
+ {
+ "id": 3068419354937669
+ },
+ {
+ "id": 3068405527726341
+ },
+ {
+ "id": 3068391002802501
+ },
+ {
+ "id": 3068370869831877
+ },
+ {
+ "id": 3068368265578821
+ },
+ {
+ "id": 3068365252905221
+ },
+ {
+ "id": 3068364464179397
+ },
+ {
+ "id": 3068357511071941
+ },
+ {
+ "id": 3068352173721925
+ },
+ {
+ "id": 3068347572291717
+ },
+ {
+ "id": 3068342732884229
+ },
+ {
+ "id": 3068336770664773
+ },
+ {
+ "id": 3068331868358789
+ },
+ {
+ "id": 3068331813521541
+ },
+ {
+ "id": 3068331758766341
+ },
+ {
+ "id": 3068327625361669
+ },
+ {
+ "id": 3068325656512773
+ },
+ {
+ "id": 3068325554260293
+ },
+ {
+ "id": 3068320089016645
+ },
+ {
+ "id": 3068303100397701
+ },
+ {
+ "id": 3068302161676421
+ },
+ {
+ "id": 3068290483226949
+ },
+ {
+ "id": 3068290124695685
+ },
+ {
+ "id": 3068290044152069
+ },
+ {
+ "id": 3068287542610181
+ },
+ {
+ "id": 3068287442798725
+ },
+ {
+ "id": 3068286573627589
+ },
+ {
+ "id": 3068274759174405
+ },
+ {
+ "id": 3068266628860165
+ },
+ {
+ "id": 3068265453193477
+ },
+ {
+ "id": 3068260351953093
+ },
+ {
+ "id": 3068260196206917
+ },
+ {
+ "id": 3068253977921861
+ },
+ {
+ "id": 3068250782402757
+ },
+ {
+ "id": 3068248546969925
+ },
+ {
+ "id": 3068247587326149
+ },
+ {
+ "id": 3068245677574277
+ },
+ {
+ "id": 3068244005472389
+ },
+ {
+ "id": 3068240723380549
+ },
+ {
+ "id": 3068238181681285
+ },
+ {
+ "id": 3068222416193797
+ },
+ {
+ "id": 3068219408025861
+ },
+ {
+ "id": 3068210285201669
+ },
+ {
+ "id": 3068205015746821
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10017,
+ "records_with_pk": 10017,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3068517744281861
+ },
+ {
+ "id": 3068516485728389
+ },
+ {
+ "id": 3068498428807429
+ },
+ {
+ "id": 3068490965305477
+ },
+ {
+ "id": 3068488957757765
+ },
+ {
+ "id": 3068478880729349
+ },
+ {
+ "id": 3068478791092357
+ },
+ {
+ "id": 3068439736813765
+ },
+ {
+ "id": 3068425153349893
+ },
+ {
+ "id": 3068420831496453
+ },
+ {
+ "id": 3068419381758085
+ },
+ {
+ "id": 3068391123650821
+ },
+ {
+ "id": 3068370907220229
+ },
+ {
+ "id": 3068368358410437
+ },
+ {
+ "id": 3068365298026821
+ },
+ {
+ "id": 3068364480170117
+ },
+ {
+ "id": 3068357527882053
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 29,
+ "records_with_pk": 29,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3068405573077317
+ },
+ {
+ "id": 3068352477743301
+ },
+ {
+ "id": 3068342767585413
+ },
+ {
+ "id": 3068303249705285
+ },
+ {
+ "id": 3068248572709125
+ },
+ {
+ "id": 3068195099363589
+ },
+ {
+ "id": 3068173056575621
+ },
+ {
+ "id": 3068173056116869
+ },
+ {
+ "id": 3068173055641733
+ },
+ {
+ "id": 3068172409686149
+ },
+ {
+ "id": 3068165922752773
+ },
+ {
+ "id": 3068161263503493
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11850,
+ "records_with_pk": 11850,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3068517741332741
+ },
+ {
+ "id": 3068516482271365
+ },
+ {
+ "id": 3068498426480901
+ },
+ {
+ "id": 3068490962798725
+ },
+ {
+ "id": 3068488953809221
+ },
+ {
+ "id": 3068478878402821
+ },
+ {
+ "id": 3068478788913285
+ },
+ {
+ "id": 3068449905166597
+ },
+ {
+ "id": 3068439734634693
+ },
+ {
+ "id": 3068425151170821
+ },
+ {
+ "id": 3068420828940549
+ },
+ {
+ "id": 3068419379562629
+ },
+ {
+ "id": 3068405569620293
+ },
+ {
+ "id": 3068391121193221
+ },
+ {
+ "id": 3068370904598789
+ },
+ {
+ "id": 3068368355690693
+ },
+ {
+ "id": 3068365295847749
+ },
+ {
+ "id": 3068364477696133
+ },
+ {
+ "id": 3068357525768517
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068361285667077
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3068517741889797
+ },
+ {
+ "id": 3068516482795653
+ },
+ {
+ "id": 3068488954612037
+ },
+ {
+ "id": 3068488954399045
+ },
+ {
+ "id": 3068405570210117
+ },
+ {
+ "id": 3068368356231365
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068193226131717
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3068490965911685
+ },
+ {
+ "id": 3068478881253637
+ },
+ {
+ "id": 3068478791747717
+ },
+ {
+ "id": 3068439737370821
+ },
+ {
+ "id": 3068425153939717
+ },
+ {
+ "id": 3068425153939718
+ },
+ {
+ "id": 3068420832184581
+ },
+ {
+ "id": 3068420832200965
+ },
+ {
+ "id": 3068419382282373
+ },
+ {
+ "id": 3068391124306181
+ },
+ {
+ "id": 3068370908072197
+ },
+ {
+ "id": 3068364481104005
+ },
+ {
+ "id": 3068357528439109
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 151,
+ "records_with_pk": 151,
+ "missing": 43,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068463611054277
+ },
+ {
+ "sitegoodsstockid": 3068463611513029
+ },
+ {
+ "sitegoodsstockid": 3068449906657541
+ },
+ {
+ "sitegoodsstockid": 3068447170857285
+ },
+ {
+ "sitegoodsstockid": 3068443071547525
+ },
+ {
+ "sitegoodsstockid": 3068443072022661
+ },
+ {
+ "sitegoodsstockid": 3068443072497798
+ },
+ {
+ "sitegoodsstockid": 3068405997390085
+ },
+ {
+ "sitegoodsstockid": 3068397306628293
+ },
+ {
+ "sitegoodsstockid": 3068396796938373
+ },
+ {
+ "sitegoodsstockid": 3068396797413509
+ },
+ {
+ "sitegoodsstockid": 3068387840166021
+ },
+ {
+ "sitegoodsstockid": 3068365194758341
+ },
+ {
+ "sitegoodsstockid": 3068364728027269
+ },
+ {
+ "sitegoodsstockid": 3068363747215621
+ },
+ {
+ "sitegoodsstockid": 3068305852975237
+ },
+ {
+ "sitegoodsstockid": 3068302319290501
+ },
+ {
+ "sitegoodsstockid": 3068299356686661
+ },
+ {
+ "sitegoodsstockid": 3068287475239173
+ },
+ {
+ "sitegoodsstockid": 3068285768239237
+ },
+ {
+ "sitegoodsstockid": 3068284328298757
+ },
+ {
+ "sitegoodsstockid": 3068284327807237
+ },
+ {
+ "sitegoodsstockid": 3068274887936325
+ },
+ {
+ "sitegoodsstockid": 3068274743986437
+ },
+ {
+ "sitegoodsstockid": 3068266527918213
+ },
+ {
+ "sitegoodsstockid": 3068264303184005
+ },
+ {
+ "sitegoodsstockid": 3068264302692485
+ },
+ {
+ "sitegoodsstockid": 3068260102326469
+ },
+ {
+ "sitegoodsstockid": 3068260102817989
+ },
+ {
+ "sitegoodsstockid": 3068251627522245
+ },
+ {
+ "sitegoodsstockid": 3068245858044101
+ },
+ {
+ "sitegoodsstockid": 3068238403602693
+ },
+ {
+ "sitegoodsstockid": 3068238398638405
+ },
+ {
+ "sitegoodsstockid": 3068230906775685
+ },
+ {
+ "sitegoodsstockid": 3068230907365509
+ },
+ {
+ "sitegoodsstockid": 3068222972643653
+ },
+ {
+ "sitegoodsstockid": 3068212484425861
+ },
+ {
+ "sitegoodsstockid": 3068212393527493
+ },
+ {
+ "sitegoodsstockid": 3068211882658053
+ },
+ {
+ "sitegoodsstockid": 3068185293736197
+ },
+ {
+ "sitegoodsstockid": 3068173817415941
+ },
+ {
+ "sitegoodsstockid": 3068166835570885
+ },
+ {
+ "sitegoodsstockid": 3068165128079621
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1747,
+ "records_with_pk": 1747,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068517745117445
+ },
+ {
+ "id": 3068516487399557
+ },
+ {
+ "id": 3068488959232325
+ },
+ {
+ "id": 3068368359033029
+ },
+ {
+ "id": 3068365298649413
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 139,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 139,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 180,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T02:43:29.763994+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18447,
+ "diff": -18446
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 99,
+ "diff": -99
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23377,
+ "diff": -11
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 38,
+ "ods": 99,
+ "diff": -61
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 1147.62,
+ "ods_sum": 2946.36,
+ "diff": -1798.7400000000002
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 1510.0,
+ "ods_sum": 5290.76,
+ "diff": -3780.76
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 5098.19,
+ "ods_sum": 18345.66,
+ "diff": -13247.470000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 123.02,
+ "diff": -123.02
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 2440.57,
+ "ods_sum": 9985.52,
+ "diff": -7544.950000000001
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18447,
+ "diff": -61
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 331403.18,
+ "diff": -1798.7399999999907
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2856,
+ "diff": -7
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 14,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4996.98,
+ "ods_sum": 5952.52,
+ "diff": -955.5400000000009
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5005,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4754,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 74,
+ "diff": -56
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 1174.0,
+ "ods_sum": 5400.0,
+ "diff": -4226.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 1174.0,
+ "ods_sum": 5290.76,
+ "diff": -4116.76
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11476,
+ "diff": -49
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 25,
+ "ods": 78,
+ "diff": -53
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 1972.0,
+ "ods_sum": 5986.0,
+ "diff": -4014.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17030,
+ "diff": -53
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 43,
+ "ods": 104,
+ "diff": -61
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 6852.0,
+ "ods_sum": 12985.0,
+ "diff": -6133.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18980
+ },
+ "generated_at": "2026-01-27T02:43:35.905375+08:00"
+ }
+ ],
+ "total_missing": 180,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T02:43:35.905402+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_history_20260127_031951.json b/etl_billiards/reports/data_integrity_history_20260127_031951.json
new file mode 100644
index 0000000..11a4ae3
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_history_20260127_031951.json
@@ -0,0 +1,1275 @@
+{
+ "mode": "history",
+ "start": "2026-01-26T00:00:00+08:00",
+ "end": "2026-01-27T00:00:00+08:00",
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-26T00:00:00+08:00",
+ "end": "2026-01-27T00:00:00+08:00",
+ "label": "week_2026-01-26",
+ "granularity": "week"
+ },
+ "api_to_ods": {
+ "window_split_unit": "month",
+ "window_compensation_hours": 2,
+ "start": "2026-01-25T22:00:00+08:00",
+ "end": "2026-01-27T02:00:00+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 137,
+ "records_with_pk": 137,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3068449874594117
+ },
+ {
+ "id": 3068439717660805
+ },
+ {
+ "id": 3068425134852421
+ },
+ {
+ "id": 3068420801906885
+ },
+ {
+ "id": 3068419354937669
+ },
+ {
+ "id": 3068405527726341
+ },
+ {
+ "id": 3068391002802501
+ },
+ {
+ "id": 3068370869831877
+ },
+ {
+ "id": 3068368265578821
+ },
+ {
+ "id": 3068365252905221
+ },
+ {
+ "id": 3068364464179397
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10018,
+ "records_with_pk": 10018,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068550021253253
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 29,
+ "records_with_pk": 29,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068405573077317
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11851,
+ "records_with_pk": 11851,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068550018664581
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 151,
+ "records_with_pk": 151,
+ "missing": 15,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068463611054277
+ },
+ {
+ "sitegoodsstockid": 3068463611513029
+ },
+ {
+ "sitegoodsstockid": 3068449906657541
+ },
+ {
+ "sitegoodsstockid": 3068447170857285
+ },
+ {
+ "sitegoodsstockid": 3068443071547525
+ },
+ {
+ "sitegoodsstockid": 3068443072022661
+ },
+ {
+ "sitegoodsstockid": 3068443072497798
+ },
+ {
+ "sitegoodsstockid": 3068405997390085
+ },
+ {
+ "sitegoodsstockid": 3068397306628293
+ },
+ {
+ "sitegoodsstockid": 3068396796938373
+ },
+ {
+ "sitegoodsstockid": 3068396797413509
+ },
+ {
+ "sitegoodsstockid": 3068387840166021
+ },
+ {
+ "sitegoodsstockid": 3068365194758341
+ },
+ {
+ "sitegoodsstockid": 3068364728027269
+ },
+ {
+ "sitegoodsstockid": 3068363747215621
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1748,
+ "records_with_pk": 1748,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068550022547589
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 139,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 139,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 30,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T03:19:45.808688+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18464,
+ "diff": -18463
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 100,
+ "diff": -100
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23434,
+ "diff": -68
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23434,
+ "diff": -68
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 38,
+ "ods": 100,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 1147.62,
+ "ods_sum": 2946.36,
+ "diff": -1798.7400000000002
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 1510.0,
+ "ods_sum": 5338.76,
+ "diff": -3828.76
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 5098.19,
+ "ods_sum": 18393.66,
+ "diff": -13295.470000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 123.02,
+ "diff": -123.02
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 2440.57,
+ "ods_sum": 9985.52,
+ "diff": -7544.950000000001
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18464,
+ "diff": -78
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2861,
+ "diff": -12
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332004.04,
+ "diff": -2399.5999999999767
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2861,
+ "diff": -12
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 12,
+ "ods": 25,
+ "diff": -13
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4996.98,
+ "ods_sum": 10333.59,
+ "diff": -5336.610000000001
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5019,
+ "diff": -16
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 18,
+ "ods": 75,
+ "diff": -57
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 1174.0,
+ "ods_sum": 5448.0,
+ "diff": -4274.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 1174.0,
+ "ods_sum": 5338.76,
+ "diff": -4164.76
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 25,
+ "ods": 79,
+ "diff": -54
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 1972.0,
+ "ods_sum": 6102.0,
+ "diff": -4130.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 43,
+ "ods": 105,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 6852.0,
+ "ods_sum": 12985.0,
+ "diff": -6133.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19196
+ },
+ "generated_at": "2026-01-27T03:19:51.836973+08:00"
+ }
+ ],
+ "total_missing": 30,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T03:19:51.836997+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260119_222704.json b/etl_billiards/reports/data_integrity_window_20260119_222704.json
new file mode 100644
index 0000000..051b7f9
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260119_222704.json
@@ -0,0 +1,1980 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T19:23:56+08:00",
+ "end": "2026-01-20T00:23:56+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T19:23:56+08:00",
+ "end": "2026-01-20T00:23:56+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-17T19:23:56+08:00",
+ "end": "2026-01-20T00:23:56+08:00",
+ "cutoff": null,
+ "window_days": 2,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058170108874053
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 286,
+ "records_with_pk": 286,
+ "missing": 67,
+ "missing_samples": [
+ {
+ "id": 3058182051252037
+ },
+ {
+ "id": 3058173240084357
+ },
+ {
+ "id": 3058171538753221
+ },
+ {
+ "id": 3058169110431429
+ },
+ {
+ "id": 3058167023896325
+ },
+ {
+ "id": 3058162035296133
+ },
+ {
+ "id": 3058161434216261
+ },
+ {
+ "id": 3058147379431301
+ },
+ {
+ "id": 3058146832598853
+ },
+ {
+ "id": 3058139319699333
+ },
+ {
+ "id": 3058135453108037
+ },
+ {
+ "id": 3058131059443589
+ },
+ {
+ "id": 3058123562878853
+ },
+ {
+ "id": 3058115682551685
+ },
+ {
+ "id": 3058114991687493
+ },
+ {
+ "id": 3058109980378949
+ },
+ {
+ "id": 3058109491381957
+ },
+ {
+ "id": 3058108377892741
+ },
+ {
+ "id": 3058107762394949
+ },
+ {
+ "id": 3058099553847045
+ },
+ {
+ "id": 3058086106400453
+ },
+ {
+ "id": 3058080098666245
+ },
+ {
+ "id": 3058077974349637
+ },
+ {
+ "id": 3058048453379909
+ },
+ {
+ "id": 3058048035342085
+ },
+ {
+ "id": 3058355401328453
+ },
+ {
+ "id": 3058353754277573
+ },
+ {
+ "id": 3058345646769925
+ },
+ {
+ "id": 3058337403520901
+ },
+ {
+ "id": 3058333255714629
+ },
+ {
+ "id": 3058333001533253
+ },
+ {
+ "id": 3058329773115205
+ },
+ {
+ "id": 3058328213751493
+ },
+ {
+ "id": 3058322441373573
+ },
+ {
+ "id": 3058318537869061
+ },
+ {
+ "id": 3058318188594949
+ },
+ {
+ "id": 3058314111092549
+ },
+ {
+ "id": 3058310941591365
+ },
+ {
+ "id": 3058307480274629
+ },
+ {
+ "id": 3058306308671301
+ },
+ {
+ "id": 3058305952237445
+ },
+ {
+ "id": 3058297604523909
+ },
+ {
+ "id": 3058295963961093
+ },
+ {
+ "id": 3058293400881029
+ },
+ {
+ "id": 3058293295007493
+ },
+ {
+ "id": 3058288670754694
+ },
+ {
+ "id": 3058288453257029
+ },
+ {
+ "id": 3058278030739269
+ },
+ {
+ "id": 3058265692653381
+ },
+ {
+ "id": 3058264531044229
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9901,
+ "records_with_pk": 9901,
+ "missing": 57,
+ "missing_samples": [
+ {
+ "id": 3058353772037829
+ },
+ {
+ "id": 3058345666463621
+ },
+ {
+ "id": 3058333274064773
+ },
+ {
+ "id": 3058333185312517
+ },
+ {
+ "id": 3058329851873157
+ },
+ {
+ "id": 3058328233346885
+ },
+ {
+ "id": 3058322463033093
+ },
+ {
+ "id": 3058318684915461
+ },
+ {
+ "id": 3058318297433989
+ },
+ {
+ "id": 3058314133325509
+ },
+ {
+ "id": 3058310958466949
+ },
+ {
+ "id": 3058307498067781
+ },
+ {
+ "id": 3058306326284165
+ },
+ {
+ "id": 3058297748064005
+ },
+ {
+ "id": 3058296864999237
+ },
+ {
+ "id": 3058293417723717
+ },
+ {
+ "id": 3058288686417669
+ },
+ {
+ "id": 3058288604628869
+ },
+ {
+ "id": 3058278080481157
+ },
+ {
+ "id": 3058265711249157
+ },
+ {
+ "id": 3058264548493125
+ },
+ {
+ "id": 3058263736223621
+ },
+ {
+ "id": 3058247691093829
+ },
+ {
+ "id": 3058243604842373
+ },
+ {
+ "id": 3058243526395781
+ },
+ {
+ "id": 3058243526363013
+ },
+ {
+ "id": 3058243526346629
+ },
+ {
+ "id": 3058236536833925
+ },
+ {
+ "id": 3058229193443141
+ },
+ {
+ "id": 3058229139408773
+ },
+ {
+ "id": 3058218392340165
+ },
+ {
+ "id": 3058215178815365
+ },
+ {
+ "id": 3058214301255493
+ },
+ {
+ "id": 3058214301288261
+ },
+ {
+ "id": 3058210811381445
+ },
+ {
+ "id": 3058207176312581
+ },
+ {
+ "id": 3058207121098629
+ },
+ {
+ "id": 3058201756452549
+ },
+ {
+ "id": 3058171555956549
+ },
+ {
+ "id": 3058167387637509
+ },
+ {
+ "id": 3058162054498053
+ },
+ {
+ "id": 3058161468622725
+ },
+ {
+ "id": 3058139340801797
+ },
+ {
+ "id": 3058135469508485
+ },
+ {
+ "id": 3058131094800133
+ },
+ {
+ "id": 3058131094783749
+ },
+ {
+ "id": 3058123580212997
+ },
+ {
+ "id": 3058116250175365
+ },
+ {
+ "id": 3058115009136389
+ },
+ {
+ "id": 3058110049371909
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 63,
+ "records_with_pk": 63,
+ "missing": 21,
+ "missing_samples": [
+ {
+ "id": 3058182126749509
+ },
+ {
+ "id": 3058131095406341
+ },
+ {
+ "id": 3058110050682629
+ },
+ {
+ "id": 3058110049814277
+ },
+ {
+ "id": 3058099614205701
+ },
+ {
+ "id": 3058048542803717
+ },
+ {
+ "id": 3058048070764293
+ },
+ {
+ "id": 3058333186787077
+ },
+ {
+ "id": 3058333186197253
+ },
+ {
+ "id": 3058318685308677
+ },
+ {
+ "id": 3058318298728325
+ },
+ {
+ "id": 3058318297909125
+ },
+ {
+ "id": 3058297748702981
+ },
+ {
+ "id": 3058243529328517
+ },
+ {
+ "id": 3058243528443781
+ },
+ {
+ "id": 3058243527624581
+ },
+ {
+ "id": 3058243527001989
+ },
+ {
+ "id": 3058236537292677
+ },
+ {
+ "id": 3058214302762821
+ },
+ {
+ "id": 3058214302304069
+ },
+ {
+ "id": 3058214301878085
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11852,
+ "records_with_pk": 11852,
+ "missing": 67,
+ "missing_samples": [
+ {
+ "id": 3058355431311109
+ },
+ {
+ "id": 3058353769318085
+ },
+ {
+ "id": 3058345664038789
+ },
+ {
+ "id": 3058337430325061
+ },
+ {
+ "id": 3058333271803781
+ },
+ {
+ "id": 3058333181052677
+ },
+ {
+ "id": 3058329848792965
+ },
+ {
+ "id": 3058328231069509
+ },
+ {
+ "id": 3058322459707141
+ },
+ {
+ "id": 3058318682146565
+ },
+ {
+ "id": 3058318293813125
+ },
+ {
+ "id": 3058314130900677
+ },
+ {
+ "id": 3058310955992965
+ },
+ {
+ "id": 3058307495577413
+ },
+ {
+ "id": 3058306323810181
+ },
+ {
+ "id": 3058305998538501
+ },
+ {
+ "id": 3058297745426181
+ },
+ {
+ "id": 3058296862607173
+ },
+ {
+ "id": 3058293415331653
+ },
+ {
+ "id": 3058293324072645
+ },
+ {
+ "id": 3058288683943685
+ },
+ {
+ "id": 3058288602089349
+ },
+ {
+ "id": 3058278077695877
+ },
+ {
+ "id": 3058265709037317
+ },
+ {
+ "id": 3058264546182981
+ },
+ {
+ "id": 3058263734110085
+ },
+ {
+ "id": 3058254330955653
+ },
+ {
+ "id": 3058247688619845
+ },
+ {
+ "id": 3058243602564997
+ },
+ {
+ "id": 3058243522529157
+ },
+ {
+ "id": 3058237363455749
+ },
+ {
+ "id": 3058236533245829
+ },
+ {
+ "id": 3058229191182149
+ },
+ {
+ "id": 3058229136951173
+ },
+ {
+ "id": 3058220401379141
+ },
+ {
+ "id": 3058218389407429
+ },
+ {
+ "id": 3058215176144773
+ },
+ {
+ "id": 3058214294751046
+ },
+ {
+ "id": 3058210808940229
+ },
+ {
+ "id": 3058207173789445
+ },
+ {
+ "id": 3058207118559109
+ },
+ {
+ "id": 3058201754011333
+ },
+ {
+ "id": 3058182124226373
+ },
+ {
+ "id": 3058173286876997
+ },
+ {
+ "id": 3058171553449797
+ },
+ {
+ "id": 3058169137661829
+ },
+ {
+ "id": 3058167385442053
+ },
+ {
+ "id": 3058162050385669
+ },
+ {
+ "id": 3058161465935749
+ },
+ {
+ "id": 3058147404957445
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16473,
+ "records_with_pk": 16473,
+ "missing": 39,
+ "missing_samples": [
+ {
+ "id": 3058357269546821
+ },
+ {
+ "id": 3058340486399685
+ },
+ {
+ "id": 3058334753851077
+ },
+ {
+ "id": 3058315070801733
+ },
+ {
+ "id": 3058310101272261
+ },
+ {
+ "id": 3058307406661317
+ },
+ {
+ "id": 3058304732399365
+ },
+ {
+ "id": 3058294051030725
+ },
+ {
+ "id": 3058268992243525
+ },
+ {
+ "id": 3058254867122053
+ },
+ {
+ "id": 3058251820943045
+ },
+ {
+ "id": 3058248490174341
+ },
+ {
+ "id": 3058247410304837
+ },
+ {
+ "id": 3058244685153989
+ },
+ {
+ "id": 3058234190661381
+ },
+ {
+ "id": 3058229070808837
+ },
+ {
+ "id": 3058227741558469
+ },
+ {
+ "id": 3058213433755397
+ },
+ {
+ "id": 3058206743906181
+ },
+ {
+ "id": 3058205389883141
+ },
+ {
+ "id": 3058204746270405
+ },
+ {
+ "id": 3058203742455621
+ },
+ {
+ "id": 3058203649296133
+ },
+ {
+ "id": 3058202633766597
+ },
+ {
+ "id": 3058184008009541
+ },
+ {
+ "id": 3058170205570821
+ },
+ {
+ "id": 3058168235132805
+ },
+ {
+ "id": 3058159083030341
+ },
+ {
+ "id": 3058154363455301
+ },
+ {
+ "id": 3058151096371013
+ },
+ {
+ "id": 3058146679768837
+ },
+ {
+ "id": 3058146260977413
+ },
+ {
+ "id": 3058110979573445
+ },
+ {
+ "id": 3058097243064133
+ },
+ {
+ "id": 3058073669682885
+ },
+ {
+ "id": 3058055359563589
+ },
+ {
+ "id": 3058054921684805
+ },
+ {
+ "id": 3058053148886789
+ },
+ {
+ "id": 3058050554840901
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2462,
+ "records_with_pk": 2462,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3058333181724421
+ },
+ {
+ "id": 3058318294419333
+ },
+ {
+ "id": 3058243010774853
+ },
+ {
+ "id": 3058243010529094
+ },
+ {
+ "id": 3058236533819269
+ },
+ {
+ "id": 3058218390030021
+ },
+ {
+ "id": 3058214295455557
+ },
+ {
+ "id": 3058182124734277
+ },
+ {
+ "id": 3058110047504133
+ },
+ {
+ "id": 3058099612026629
+ },
+ {
+ "id": 3058048539952901
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8267,
+ "records_with_pk": 8267,
+ "missing": 62,
+ "missing_samples": [
+ {
+ "id": 3058353772709573
+ },
+ {
+ "id": 3058345667741573
+ },
+ {
+ "id": 3058333274752901
+ },
+ {
+ "id": 3058329852659589
+ },
+ {
+ "id": 3058329852659590
+ },
+ {
+ "id": 3058328233854789
+ },
+ {
+ "id": 3058318686177029
+ },
+ {
+ "id": 3058314133898949
+ },
+ {
+ "id": 3058310959236997
+ },
+ {
+ "id": 3058307498706757
+ },
+ {
+ "id": 3058306326873989
+ },
+ {
+ "id": 3058296865638213
+ },
+ {
+ "id": 3058293418231621
+ },
+ {
+ "id": 3058288687056645
+ },
+ {
+ "id": 3058288605464453
+ },
+ {
+ "id": 3058288605480837
+ },
+ {
+ "id": 3058288605464454
+ },
+ {
+ "id": 3058288605464455
+ },
+ {
+ "id": 3058288605464456
+ },
+ {
+ "id": 3058278081152901
+ },
+ {
+ "id": 3058265711855365
+ },
+ {
+ "id": 3058264549656389
+ },
+ {
+ "id": 3058263736747909
+ },
+ {
+ "id": 3058247691962181
+ },
+ {
+ "id": 3058243605923717
+ },
+ {
+ "id": 3058229194262341
+ },
+ {
+ "id": 3058229140146053
+ },
+ {
+ "id": 3058215179405189
+ },
+ {
+ "id": 3058210812036805
+ },
+ {
+ "id": 3058207177033477
+ },
+ {
+ "id": 3058207121688453
+ },
+ {
+ "id": 3058201757140677
+ },
+ {
+ "id": 3058171556677445
+ },
+ {
+ "id": 3058171556693829
+ },
+ {
+ "id": 3058167388325637
+ },
+ {
+ "id": 3058167388325638
+ },
+ {
+ "id": 3058162055055109
+ },
+ {
+ "id": 3058161469245317
+ },
+ {
+ "id": 3058139341473541
+ },
+ {
+ "id": 3058139341473542
+ },
+ {
+ "id": 3058135470049157
+ },
+ {
+ "id": 3058123580983045
+ },
+ {
+ "id": 3058123580983046
+ },
+ {
+ "id": 3058116250814341
+ },
+ {
+ "id": 3058115009758981
+ },
+ {
+ "id": 3058109512632197
+ },
+ {
+ "id": 3058108394653445
+ },
+ {
+ "id": 3058107782285189
+ },
+ {
+ "id": 3058086123947845
+ },
+ {
+ "id": 3058080118032261
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 341,
+ "records_with_pk": 341,
+ "missing": 126,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3058173288646469
+ },
+ {
+ "sitegoodsstockid": 3058169139349381
+ },
+ {
+ "sitegoodsstockid": 3058153735833413
+ },
+ {
+ "sitegoodsstockid": 3058153653733061
+ },
+ {
+ "sitegoodsstockid": 3058152982710085
+ },
+ {
+ "sitegoodsstockid": 3058147406464773
+ },
+ {
+ "sitegoodsstockid": 3058146857027333
+ },
+ {
+ "sitegoodsstockid": 3058143716722565
+ },
+ {
+ "sitegoodsstockid": 3058136377722693
+ },
+ {
+ "sitegoodsstockid": 3058112244287301
+ },
+ {
+ "sitegoodsstockid": 3058110304143109
+ },
+ {
+ "sitegoodsstockid": 3058109840033541
+ },
+ {
+ "sitegoodsstockid": 3058090960586437
+ },
+ {
+ "sitegoodsstockid": 3058077998745477
+ },
+ {
+ "sitegoodsstockid": 3058064944367365
+ },
+ {
+ "sitegoodsstockid": 3058053009983173
+ },
+ {
+ "sitegoodsstockid": 3058053009491653
+ },
+ {
+ "sitegoodsstockid": 3058019621128069
+ },
+ {
+ "sitegoodsstockid": 3057970083939845
+ },
+ {
+ "sitegoodsstockid": 3057932420679557
+ },
+ {
+ "sitegoodsstockid": 3057932420237189
+ },
+ {
+ "sitegoodsstockid": 3057926094030661
+ },
+ {
+ "sitegoodsstockid": 3057925720311493
+ },
+ {
+ "sitegoodsstockid": 3057925720786629
+ },
+ {
+ "sitegoodsstockid": 3057925719836357
+ },
+ {
+ "sitegoodsstockid": 3057893627709189
+ },
+ {
+ "sitegoodsstockid": 3057843657230085
+ },
+ {
+ "sitegoodsstockid": 3057786863699781
+ },
+ {
+ "sitegoodsstockid": 3057735409518277
+ },
+ {
+ "sitegoodsstockid": 3057702194824965
+ },
+ {
+ "sitegoodsstockid": 3057689507858117
+ },
+ {
+ "sitegoodsstockid": 3057689507366597
+ },
+ {
+ "sitegoodsstockid": 3057552809871173
+ },
+ {
+ "sitegoodsstockid": 3057500130559749
+ },
+ {
+ "sitegoodsstockid": 3057464372889477
+ },
+ {
+ "sitegoodsstockid": 3057464372447109
+ },
+ {
+ "sitegoodsstockid": 3057449635743557
+ },
+ {
+ "sitegoodsstockid": 3057449150596869
+ },
+ {
+ "sitegoodsstockid": 3057449150105349
+ },
+ {
+ "sitegoodsstockid": 3057376085329669
+ },
+ {
+ "sitegoodsstockid": 3057370028885765
+ },
+ {
+ "sitegoodsstockid": 3057367488546629
+ },
+ {
+ "sitegoodsstockid": 3057334818457349
+ },
+ {
+ "sitegoodsstockid": 3057283158640389
+ },
+ {
+ "sitegoodsstockid": 3057283159115525
+ },
+ {
+ "sitegoodsstockid": 3057249985480517
+ },
+ {
+ "sitegoodsstockid": 3057238611035909
+ },
+ {
+ "sitegoodsstockid": 3057214401595269
+ },
+ {
+ "sitegoodsstockid": 3057193758230341
+ },
+ {
+ "sitegoodsstockid": 3057193758721861
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1676,
+ "records_with_pk": 1676,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3058318300202885
+ },
+ {
+ "id": 3058297749505797
+ },
+ {
+ "id": 3058296865769285
+ },
+ {
+ "id": 3058243531163525
+ },
+ {
+ "id": 3058218393208517
+ },
+ {
+ "id": 3058214303958853
+ },
+ {
+ "id": 3058214303909701
+ },
+ {
+ "id": 3058110052189957
+ },
+ {
+ "id": 3058048543442693
+ },
+ {
+ "id": 3057979151484421
+ },
+ {
+ "id": 3057859470346117
+ },
+ {
+ "id": 3057795512338117
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 294,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 294,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 463,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T22:26:58.735784+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22514,
+ "ods": 22514,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22514,
+ "ods": 22514,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 196,
+ "ods": 196,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 5094.99,
+ "ods_sum": 5094.99,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 10380.83,
+ "ods_sum": 10380.83,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 24021.05,
+ "ods_sum": 24021.05,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 892.14,
+ "ods_sum": 892.14,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 9437.37,
+ "ods_sum": 9437.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17615,
+ "ods": 17615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2710,
+ "ods": 2710,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 311771.56,
+ "ods_sum": 311771.56,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2710,
+ "ods": 2710,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 536840,
+ "ods": 17563,
+ "diff": 519277
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 658625.3,
+ "ods_sum": 21673.2,
+ "diff": 636952.1000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 46,
+ "ods": 46,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 19807.75,
+ "ods_sum": 19807.75,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4771,
+ "ods": 4771,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4592,
+ "ods": 4592,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4592,
+ "ods": 4592,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 152,
+ "ods": 152,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 10142.0,
+ "ods_sum": 10142.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 9832.83,
+ "ods_sum": 9832.83,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10861,
+ "ods": 10861,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 169,
+ "ods": 169,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 12018.0,
+ "ods_sum": 12018.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16434,
+ "ods": 16434,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 442,
+ "ods": 442,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 442,
+ "ods": 442,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 226,
+ "ods": 226,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 21838.0,
+ "ods_sum": 21838.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 519277
+ },
+ "generated_at": "2026-01-19T22:27:04.028446+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 463,
+ "total_errors": 0
+ },
+ "total_missing": 463,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T22:27:04.028467+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260119_233704.json b/etl_billiards/reports/data_integrity_window_20260119_233704.json
new file mode 100644
index 0000000..aba8ec2
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260119_233704.json
@@ -0,0 +1,1311 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T20:31:25+08:00",
+ "end": "2026-01-20T01:31:25+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T20:31:25+08:00",
+ "end": "2026-01-20T01:31:25+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-17T20:31:25+08:00",
+ "end": "2026-01-20T01:31:25+08:00",
+ "cutoff": null,
+ "window_days": 2,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 288,
+ "records_with_pk": 288,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9913,
+ "records_with_pk": 9913,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 65,
+ "records_with_pk": 65,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11866,
+ "records_with_pk": 11866,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058428623472325
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16477,
+ "records_with_pk": 16477,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2465,
+ "records_with_pk": 2465,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8275,
+ "records_with_pk": 8275,
+ "missing": 70,
+ "missing_samples": [
+ {
+ "id": 3058416406071045
+ },
+ {
+ "id": 3058405159372613
+ },
+ {
+ "id": 3058399523604293
+ },
+ {
+ "id": 3058374049761157
+ },
+ {
+ "id": 3058369719568261
+ },
+ {
+ "id": 3058366791796421
+ },
+ {
+ "id": 3058364256405381
+ },
+ {
+ "id": 3058364256405382
+ },
+ {
+ "id": 3058353772709573
+ },
+ {
+ "id": 3058345667741573
+ },
+ {
+ "id": 3058333274752901
+ },
+ {
+ "id": 3058329852659589
+ },
+ {
+ "id": 3058329852659590
+ },
+ {
+ "id": 3058328233854789
+ },
+ {
+ "id": 3058318686177029
+ },
+ {
+ "id": 3058314133898949
+ },
+ {
+ "id": 3058310959236997
+ },
+ {
+ "id": 3058307498706757
+ },
+ {
+ "id": 3058306326873989
+ },
+ {
+ "id": 3058296865638213
+ },
+ {
+ "id": 3058293418231621
+ },
+ {
+ "id": 3058288687056645
+ },
+ {
+ "id": 3058288605464453
+ },
+ {
+ "id": 3058288605480837
+ },
+ {
+ "id": 3058288605464454
+ },
+ {
+ "id": 3058288605464455
+ },
+ {
+ "id": 3058288605464456
+ },
+ {
+ "id": 3058278081152901
+ },
+ {
+ "id": 3058265711855365
+ },
+ {
+ "id": 3058264549656389
+ },
+ {
+ "id": 3058263736747909
+ },
+ {
+ "id": 3058247691962181
+ },
+ {
+ "id": 3058243605923717
+ },
+ {
+ "id": 3058229194262341
+ },
+ {
+ "id": 3058229140146053
+ },
+ {
+ "id": 3058215179405189
+ },
+ {
+ "id": 3058210812036805
+ },
+ {
+ "id": 3058207177033477
+ },
+ {
+ "id": 3058207121688453
+ },
+ {
+ "id": 3058201757140677
+ },
+ {
+ "id": 3058171556677445
+ },
+ {
+ "id": 3058171556693829
+ },
+ {
+ "id": 3058167388325637
+ },
+ {
+ "id": 3058167388325638
+ },
+ {
+ "id": 3058162055055109
+ },
+ {
+ "id": 3058161469245317
+ },
+ {
+ "id": 3058139341473541
+ },
+ {
+ "id": 3058139341473542
+ },
+ {
+ "id": 3058135470049157
+ },
+ {
+ "id": 3058123580983045
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 323,
+ "records_with_pk": 323,
+ "missing": 133,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3058248105920197
+ },
+ {
+ "sitegoodsstockid": 3058245559994117
+ },
+ {
+ "sitegoodsstockid": 3058245560600325
+ },
+ {
+ "sitegoodsstockid": 3058245414749893
+ },
+ {
+ "sitegoodsstockid": 3058245416519365
+ },
+ {
+ "sitegoodsstockid": 3058245415290565
+ },
+ {
+ "sitegoodsstockid": 3058245415880389
+ },
+ {
+ "sitegoodsstockid": 3058245414192837
+ },
+ {
+ "sitegoodsstockid": 3058237364979461
+ },
+ {
+ "sitegoodsstockid": 3058235144652549
+ },
+ {
+ "sitegoodsstockid": 3058232910006085
+ },
+ {
+ "sitegoodsstockid": 3058231257483141
+ },
+ {
+ "sitegoodsstockid": 3058229962933957
+ },
+ {
+ "sitegoodsstockid": 3058228258473733
+ },
+ {
+ "sitegoodsstockid": 3058220403083077
+ },
+ {
+ "sitegoodsstockid": 3058216641545926
+ },
+ {
+ "sitegoodsstockid": 3058216548861701
+ },
+ {
+ "sitegoodsstockid": 3058216042448645
+ },
+ {
+ "sitegoodsstockid": 3058215916619525
+ },
+ {
+ "sitegoodsstockid": 3058215917143813
+ },
+ {
+ "sitegoodsstockid": 3058215917700869
+ },
+ {
+ "sitegoodsstockid": 3058213697832709
+ },
+ {
+ "sitegoodsstockid": 3058213014423429
+ },
+ {
+ "sitegoodsstockid": 3058213014914949
+ },
+ {
+ "sitegoodsstockid": 3058208837617413
+ },
+ {
+ "sitegoodsstockid": 3058203817510597
+ },
+ {
+ "sitegoodsstockid": 3058201680774917
+ },
+ {
+ "sitegoodsstockid": 3058185142880133
+ },
+ {
+ "sitegoodsstockid": 3058185143371653
+ },
+ {
+ "sitegoodsstockid": 3058173288646469
+ },
+ {
+ "sitegoodsstockid": 3058169139349381
+ },
+ {
+ "sitegoodsstockid": 3058153735833413
+ },
+ {
+ "sitegoodsstockid": 3058153653733061
+ },
+ {
+ "sitegoodsstockid": 3058152982710085
+ },
+ {
+ "sitegoodsstockid": 3058147406464773
+ },
+ {
+ "sitegoodsstockid": 3058146857027333
+ },
+ {
+ "sitegoodsstockid": 3058143716722565
+ },
+ {
+ "sitegoodsstockid": 3058136377722693
+ },
+ {
+ "sitegoodsstockid": 3058112244287301
+ },
+ {
+ "sitegoodsstockid": 3058110304143109
+ },
+ {
+ "sitegoodsstockid": 3058109840033541
+ },
+ {
+ "sitegoodsstockid": 3058090960586437
+ },
+ {
+ "sitegoodsstockid": 3058077998745477
+ },
+ {
+ "sitegoodsstockid": 3058064944367365
+ },
+ {
+ "sitegoodsstockid": 3058053009983173
+ },
+ {
+ "sitegoodsstockid": 3058053009491653
+ },
+ {
+ "sitegoodsstockid": 3058019621128069
+ },
+ {
+ "sitegoodsstockid": 3057970083939845
+ },
+ {
+ "sitegoodsstockid": 3057932420679557
+ },
+ {
+ "sitegoodsstockid": 3057932420237189
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1676,
+ "records_with_pk": 1676,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3058318300202885
+ },
+ {
+ "id": 3058297749505797
+ },
+ {
+ "id": 3058296865769285
+ },
+ {
+ "id": 3058243531163525
+ },
+ {
+ "id": 3058218393208517
+ },
+ {
+ "id": 3058214303958853
+ },
+ {
+ "id": 3058214303909701
+ },
+ {
+ "id": 3058110052189957
+ },
+ {
+ "id": 3058048543442693
+ },
+ {
+ "id": 3057979151484421
+ },
+ {
+ "id": 3057859470346117
+ },
+ {
+ "id": 3057795512338117
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 298,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 298,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 216,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T23:36:58.642196+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22594,
+ "ods": 22594,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22594,
+ "ods": 22594,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 257,
+ "ods": 257,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 6374.1,
+ "ods_sum": 6374.1,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 14029.53,
+ "ods_sum": 14029.53,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 31168.25,
+ "ods_sum": 31168.25,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 881.16,
+ "ods_sum": 881.16,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 11645.78,
+ "ods_sum": 11645.78,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17684,
+ "ods": 17684,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2710,
+ "ods": 2710,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 311771.56,
+ "ods_sum": 311771.56,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2710,
+ "ods": 2710,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 554403,
+ "ods": 17563,
+ "diff": 536840
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 680298.5,
+ "ods_sum": 21673.2,
+ "diff": 658625.3
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 26339.1,
+ "ods_sum": 26339.1,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4794,
+ "ods": 4794,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4606,
+ "ods": 4606,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4606,
+ "ods": 4606,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 144,
+ "ods": 144,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 9748.0,
+ "ods_sum": 9748.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 9438.83,
+ "ods_sum": 9438.83,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10861,
+ "ods": 10861,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 201,
+ "ods": 201,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 13526.0,
+ "ods_sum": 13526.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16477,
+ "ods": 16477,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 443,
+ "ods": 443,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 443,
+ "ods": 443,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 296,
+ "ods": 296,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 32690.0,
+ "ods_sum": 32690.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 536840
+ },
+ "generated_at": "2026-01-19T23:37:04.440573+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 216,
+ "total_errors": 0
+ },
+ "total_missing": 216,
+ "total_errors": 0,
+ "generated_at": "2026-01-19T23:37:04.440595+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260120_003547.json b/etl_billiards/reports/data_integrity_window_20260120_003547.json
new file mode 100644
index 0000000..51ed7d9
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260120_003547.json
@@ -0,0 +1,1096 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-09T21:21:28+08:00",
+ "end": "2026-01-20T02:21:28+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-09T21:21:28+08:00",
+ "end": "2026-01-20T02:21:28+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-09T21:21:28+08:00",
+ "end": "2026-01-20T02:21:28+08:00",
+ "cutoff": null,
+ "window_days": 10,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1245,
+ "records_with_pk": 1245,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3058483012732741
+ },
+ {
+ "id": 3058482606163717
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9922,
+ "records_with_pk": 9922,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3058483098863365
+ },
+ {
+ "id": 3058482682840837
+ },
+ {
+ "id": 3058482682824453
+ },
+ {
+ "id": 3058482682857221
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 292,
+ "records_with_pk": 292,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3058482685036293
+ },
+ {
+ "id": 3058482684462853
+ },
+ {
+ "id": 3058482683823877
+ },
+ {
+ "id": 3058482683381509
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11877,
+ "records_with_pk": 11877,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3058485277132549
+ },
+ {
+ "id": 3058483096176389
+ },
+ {
+ "id": 3058482678597381
+ },
+ {
+ "id": 3058475842094789
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2467,
+ "records_with_pk": 2467,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3058483096749829
+ },
+ {
+ "id": 3058482679121669
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 27,
+ "records_with_pk": 27,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8278,
+ "records_with_pk": 8278,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3058475845404357
+ },
+ {
+ "id": 3058466194228933
+ },
+ {
+ "id": 3058437829232389
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1727,
+ "records_with_pk": 1727,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3058485278623493
+ },
+ {
+ "sitegoodsstockid": 3058465513735941
+ },
+ {
+ "sitegoodsstockid": 3058457516246853
+ },
+ {
+ "sitegoodsstockid": 3058454206695237
+ },
+ {
+ "sitegoodsstockid": 3058454206252869
+ },
+ {
+ "sitegoodsstockid": 3058454007760709
+ },
+ {
+ "sitegoodsstockid": 3058452731971269
+ },
+ {
+ "sitegoodsstockid": 3058452593346245
+ },
+ {
+ "sitegoodsstockid": 3058449180509893
+ },
+ {
+ "sitegoodsstockid": 3058446892353413
+ },
+ {
+ "sitegoodsstockid": 3058446799439621
+ },
+ {
+ "sitegoodsstockid": 3058440464910085
+ },
+ {
+ "sitegoodsstockid": 3058438043469573
+ },
+ {
+ "sitegoodsstockid": 3058433085507461
+ },
+ {
+ "sitegoodsstockid": 3058432235865861
+ },
+ {
+ "sitegoodsstockid": 3058429165078213
+ },
+ {
+ "sitegoodsstockid": 3058428628174533
+ }
+ ],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1682,
+ "records_with_pk": 1682,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3058483099567877
+ },
+ {
+ "id": 3058482686527237
+ },
+ {
+ "id": 3058482686478085
+ },
+ {
+ "id": 3058455038052101
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1291,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 1291,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T00:35:42.277919+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22603,
+ "ods": 22603,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22603,
+ "ods": 22603,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1094,
+ "ods": 1094,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 25642.61,
+ "ods_sum": 25642.61,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 57942.9,
+ "ods_sum": 57942.9,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 132700.58,
+ "ods_sum": 132700.58,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 8020.96,
+ "ods_sum": 8020.96,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 52705.81,
+ "ods_sum": 52705.81,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17689,
+ "ods": 17689,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2722,
+ "ods": 2722,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 314293.85,
+ "ods_sum": 314293.85,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2722,
+ "ods": 2722,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 571966,
+ "ods": 17563,
+ "diff": 554403
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 701971.7,
+ "ods_sum": 21673.2,
+ "diff": 680298.5
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 292,
+ "ods": 292,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 91164.82,
+ "ods_sum": 91164.82,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4795,
+ "ods": 4795,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4606,
+ "ods": 4606,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4606,
+ "ods": 4606,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 922,
+ "ods": 922,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 60018.0,
+ "ods_sum": 60018.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 57798.9,
+ "ods_sum": 57798.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10931,
+ "ods": 10931,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 918,
+ "ods": 918,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 59546.0,
+ "ods_sum": 59546.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 443,
+ "ods": 443,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 443,
+ "ods": 443,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1286,
+ "ods": 1286,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 148923.0,
+ "ods_sum": 148923.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -43.0,
+ "ods_sum": -43.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 554403
+ },
+ "generated_at": "2026-01-20T00:35:47.490653+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 40,
+ "total_errors": 0
+ },
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T00:35:47.490693+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260120_023005.json b/etl_billiards/reports/data_integrity_window_20260120_023005.json
new file mode 100644
index 0000000..6c1f4f1
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260120_023005.json
@@ -0,0 +1,1041 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-09T23:24:45+08:00",
+ "end": "2026-01-20T04:24:45+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-09T23:24:45+08:00",
+ "end": "2026-01-20T04:24:45+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-09T23:24:45+08:00",
+ "end": "2026-01-20T04:24:45+08:00",
+ "cutoff": null,
+ "window_days": 10,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1238,
+ "records_with_pk": 1238,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 301,
+ "records_with_pk": 301,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11894,
+ "records_with_pk": 11894,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3058596368844613
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 28,
+ "records_with_pk": 28,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3058553635129221
+ },
+ {
+ "id": 3058510524663493
+ },
+ {
+ "id": 3058510230161157
+ },
+ {
+ "id": 3058504497694469
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1707,
+ "records_with_pk": 1707,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3058582867199685
+ },
+ {
+ "sitegoodsstockid": 3058560300435269
+ },
+ {
+ "sitegoodsstockid": 3058535821920133
+ },
+ {
+ "sitegoodsstockid": 3058528979666693
+ },
+ {
+ "sitegoodsstockid": 3058528863651717
+ },
+ {
+ "sitegoodsstockid": 3058528765888325
+ },
+ {
+ "sitegoodsstockid": 3058528636077893
+ },
+ {
+ "sitegoodsstockid": 3058507817436933
+ },
+ {
+ "sitegoodsstockid": 3058500774905605
+ },
+ {
+ "sitegoodsstockid": 3058485278623493
+ }
+ ],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3058536031192773
+ },
+ {
+ "id": 3058529163675333
+ },
+ {
+ "id": 3058513988355781
+ },
+ {
+ "id": 3058513157326661
+ },
+ {
+ "id": 3058509258360645
+ },
+ {
+ "id": 3058509258409797
+ },
+ {
+ "id": 3058496802391941
+ },
+ {
+ "id": 3058496802359173
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1283,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 1283,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 23,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T02:30:00.503232+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1095,
+ "ods": 1095,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 26529.01,
+ "ods_sum": 26529.01,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 57230.5,
+ "ods_sum": 57230.5,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 134105.34,
+ "ods_sum": 134105.34,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 7778.22,
+ "ods_sum": 7778.22,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 53936.57,
+ "ods_sum": 53936.57,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2728,
+ "ods": 2728,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 314830.9,
+ "ods_sum": 314830.9,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2728,
+ "ods": 2728,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 589529,
+ "ods": 17563,
+ "diff": 571966
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 723644.9,
+ "ods_sum": 21673.2,
+ "diff": 701971.7000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 305,
+ "ods": 305,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93900.01,
+ "ods_sum": 93900.01,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 910,
+ "ods": 910,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 59250.0,
+ "ods_sum": 59250.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 57038.5,
+ "ods_sum": 57038.5,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10934,
+ "ods": 10934,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 908,
+ "ods": 908,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 58814.0,
+ "ods_sum": 58814.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1282,
+ "ods": 1282,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 153614.0,
+ "ods_sum": 153614.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -43.0,
+ "ods_sum": -43.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 571966
+ },
+ "generated_at": "2026-01-20T02:30:05.600935+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 23,
+ "total_errors": 0
+ },
+ "total_missing": 23,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T02:30:05.600959+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260120_034306.json b/etl_billiards/reports/data_integrity_window_20260120_034306.json
new file mode 100644
index 0000000..27b3c2a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260120_034306.json
@@ -0,0 +1,972 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-10T00:37:58+08:00",
+ "end": "2026-01-20T05:37:58+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-10T00:37:58+08:00",
+ "end": "2026-01-20T05:37:58+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-10T00:37:58+08:00",
+ "end": "2026-01-20T05:37:58+08:00",
+ "cutoff": null,
+ "window_days": 10,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1234,
+ "records_with_pk": 1234,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9940,
+ "records_with_pk": 9940,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 299,
+ "records_with_pk": 299,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11894,
+ "records_with_pk": 11894,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16480,
+ "records_with_pk": 16480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 28,
+ "records_with_pk": 28,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8282,
+ "records_with_pk": 8282,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1689,
+ "records_with_pk": 1689,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3058615392274245
+ }
+ ],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1690,
+ "records_with_pk": 1690,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1279,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 1279,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T03:43:01.888371+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22622,
+ "ods": 22622,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 1091,
+ "ods": 1091,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 26391.76,
+ "ods_sum": 26391.76,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 56895.59,
+ "ods_sum": 56895.59,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 133626.16,
+ "ods_sum": 133626.16,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 7778.22,
+ "ods_sum": 7778.22,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 53929.55,
+ "ods_sum": 53929.55,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17711,
+ "ods": 17711,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 607092,
+ "ods": 17563,
+ "diff": 589529
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 745318.1,
+ "ods_sum": 21673.2,
+ "diff": 723644.9
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 303,
+ "ods": 303,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 190.72,
+ "ods_sum": 190.72,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 93547.06,
+ "ods_sum": 93547.06,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4811,
+ "ods": 4811,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4615,
+ "ods": 4615,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 910,
+ "ods": 910,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 59094.0,
+ "ods_sum": 59094.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 56895.59,
+ "ods_sum": 56895.59,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 905,
+ "ods": 905,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 58612.0,
+ "ods_sum": 58612.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16480,
+ "ods": 16480,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 444,
+ "ods": 444,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1279,
+ "ods": 1279,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 153388.0,
+ "ods_sum": 153388.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 3,
+ "ods": 3,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -43.0,
+ "ods_sum": -43.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 589529
+ },
+ "generated_at": "2026-01-20T03:43:06.774768+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 1,
+ "total_errors": 0
+ },
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T03:43:06.774790+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260120_162840.json b/etl_billiards/reports/data_integrity_window_20260120_162840.json
new file mode 100644
index 0000000..e6ac523
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260120_162840.json
@@ -0,0 +1,1048 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T13:22:34+08:00",
+ "end": "2026-01-20T18:22:34+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T13:22:34+08:00",
+ "end": "2026-01-20T18:22:34+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-19T13:22:34+08:00",
+ "end": "2026-01-20T18:22:34+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 135,
+ "records_with_pk": 135,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9838,
+ "records_with_pk": 9838,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 46,
+ "records_with_pk": 46,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11759,
+ "records_with_pk": 11759,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16495,
+ "records_with_pk": 16495,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 554,
+ "records_with_pk": 554,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 943,
+ "records_with_pk": 943,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2461,
+ "records_with_pk": 2461,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8175,
+ "records_with_pk": 8175,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3059411450791813
+ },
+ {
+ "id": 3059348421445317
+ },
+ {
+ "id": 3059348361512709
+ },
+ {
+ "id": 3059281038296901
+ },
+ {
+ "id": 3059280986539717
+ },
+ {
+ "id": 3059280930342662
+ },
+ {
+ "id": 3059280930342661
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 135,
+ "records_with_pk": 135,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3059220582418181
+ },
+ {
+ "sitegoodsstockid": 3058856419280773
+ },
+ {
+ "sitegoodsstockid": 3058802400266053
+ },
+ {
+ "sitegoodsstockid": 3058778158368453
+ },
+ {
+ "sitegoodsstockid": 3058744894687045
+ },
+ {
+ "sitegoodsstockid": 3058744895145797
+ },
+ {
+ "sitegoodsstockid": 3058744894195525
+ },
+ {
+ "sitegoodsstockid": 3058698424371077
+ },
+ {
+ "sitegoodsstockid": 3058698424862597
+ },
+ {
+ "sitegoodsstockid": 3058686747543365
+ },
+ {
+ "sitegoodsstockid": 3058686747395909
+ },
+ {
+ "sitegoodsstockid": 3058680780457861
+ },
+ {
+ "sitegoodsstockid": 3059380517717765
+ },
+ {
+ "sitegoodsstockid": 3059380517275397
+ },
+ {
+ "sitegoodsstockid": 3059380516833029
+ },
+ {
+ "sitegoodsstockid": 3059380516374277
+ },
+ {
+ "sitegoodsstockid": 3059368663238341
+ },
+ {
+ "sitegoodsstockid": 3059330587133829
+ },
+ {
+ "sitegoodsstockid": 3059324970223493
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1685,
+ "records_with_pk": 1685,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 138,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 138,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 26,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T16:28:33.150957+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22636,
+ "ods": 22636,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22636,
+ "ods": 22636,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 117,
+ "ods": 117,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 2966.82,
+ "ods_sum": 2966.82,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 5358.7,
+ "ods_sum": 5358.7,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14259.68,
+ "ods_sum": 14259.68,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 251.56,
+ "ods_sum": 251.56,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 6185.72,
+ "ods_sum": 6185.72,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17721,
+ "ods": 17721,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 624655,
+ "ods": 17563,
+ "diff": 607092
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 766991.3,
+ "ods_sum": 21673.2,
+ "diff": 745318.1000000001
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 46,
+ "ods": 46,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14396.05,
+ "ods_sum": 14396.05,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4814,
+ "ods": 4814,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 92,
+ "ods": 92,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4620,
+ "ods": 4620,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4620,
+ "ods": 4620,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 77,
+ "ods": 77,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 5290.0,
+ "ods_sum": 5290.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4926.7,
+ "ods_sum": 4926.7,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10938,
+ "ods": 10938,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 90,
+ "ods": 90,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 6156.0,
+ "ods_sum": 6156.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16495,
+ "ods": 16495,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 445,
+ "ods": 445,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 445,
+ "ods": 445,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 138,
+ "ods": 138,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 19975.0,
+ "ods_sum": 19975.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 43,
+ "ods": 43,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 607092
+ },
+ "generated_at": "2026-01-20T16:28:40.403997+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 26,
+ "total_errors": 0
+ },
+ "total_missing": 26,
+ "total_errors": 0,
+ "generated_at": "2026-01-20T16:28:40.404020+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260122_235540.json b/etl_billiards/reports/data_integrity_window_20260122_235540.json
new file mode 100644
index 0000000..590bd1a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260122_235540.json
@@ -0,0 +1,1412 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T20:49:49+08:00",
+ "end": "2026-01-23T01:49:49+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-17T20:49:49+08:00",
+ "end": "2026-01-23T01:49:49+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-17T20:49:49+08:00",
+ "end": "2026-01-23T01:49:49+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 622,
+ "records_with_pk": 622,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3062692637429381
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9951,
+ "records_with_pk": 9951,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3062692655173061
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 154,
+ "records_with_pk": 154,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11837,
+ "records_with_pk": 11837,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3062692652993989
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16707,
+ "records_with_pk": 16707,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 84,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 555,
+ "records_with_pk": 555,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 944,
+ "records_with_pk": 944,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16,
+ "records_with_pk": 16,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8239,
+ "records_with_pk": 8239,
+ "missing": 212,
+ "missing_samples": [
+ {
+ "id": 3062692656025029
+ },
+ {
+ "id": 3062674787831365
+ },
+ {
+ "id": 3062664923729477
+ },
+ {
+ "id": 3062652072480197
+ },
+ {
+ "id": 3062652072480198
+ },
+ {
+ "id": 3062632657374661
+ },
+ {
+ "id": 3062618836602437
+ },
+ {
+ "id": 3062611506695749
+ },
+ {
+ "id": 3062611506712133
+ },
+ {
+ "id": 3062602723872325
+ },
+ {
+ "id": 3062602664808005
+ },
+ {
+ "id": 3062599133335045
+ },
+ {
+ "id": 3062598651956869
+ },
+ {
+ "id": 3062597974085253
+ },
+ {
+ "id": 3062597325983237
+ },
+ {
+ "id": 3062591465049733
+ },
+ {
+ "id": 3062574558383685
+ },
+ {
+ "id": 3062572271553989
+ },
+ {
+ "id": 3062555998293637
+ },
+ {
+ "id": 3062552371498501
+ },
+ {
+ "id": 3062552314416773
+ },
+ {
+ "id": 3062542602030597
+ },
+ {
+ "id": 3062536547929733
+ },
+ {
+ "id": 3062530887110213
+ },
+ {
+ "id": 3062523678543493
+ },
+ {
+ "id": 3062523627048389
+ },
+ {
+ "id": 3062523627048390
+ },
+ {
+ "id": 3062523627048391
+ },
+ {
+ "id": 3062513470492229
+ },
+ {
+ "id": 3062513418931653
+ },
+ {
+ "id": 3062512330182213
+ },
+ {
+ "id": 3062507931880965
+ },
+ {
+ "id": 3062479559544325
+ },
+ {
+ "id": 3062476447518213
+ },
+ {
+ "id": 3062462698589701
+ },
+ {
+ "id": 3062449941220997
+ },
+ {
+ "id": 3062406698290821
+ },
+ {
+ "id": 3062405758471749
+ },
+ {
+ "id": 3062405758471750
+ },
+ {
+ "id": 3062395024903749
+ },
+ {
+ "id": 3062395024903750
+ },
+ {
+ "id": 3062390218837573
+ },
+ {
+ "id": 3062386556718533
+ },
+ {
+ "id": 3062381028396613
+ },
+ {
+ "id": 3062381028396614
+ },
+ {
+ "id": 3062368420204165
+ },
+ {
+ "id": 3062351233207813
+ },
+ {
+ "id": 3062335732649477
+ },
+ {
+ "id": 3062332036009605
+ },
+ {
+ "id": 3062332036009606
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 827,
+ "records_with_pk": 827,
+ "missing": 465,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3062510192938437
+ },
+ {
+ "sitegoodsstockid": 3062497709723141
+ },
+ {
+ "sitegoodsstockid": 3062495030250949
+ },
+ {
+ "sitegoodsstockid": 3062493529886149
+ },
+ {
+ "sitegoodsstockid": 3062492534705733
+ },
+ {
+ "sitegoodsstockid": 3062491449740741
+ },
+ {
+ "sitegoodsstockid": 3062491217989189
+ },
+ {
+ "sitegoodsstockid": 3062487503277573
+ },
+ {
+ "sitegoodsstockid": 3062479336951365
+ },
+ {
+ "sitegoodsstockid": 3062478763052549
+ },
+ {
+ "sitegoodsstockid": 3062478394265029
+ },
+ {
+ "sitegoodsstockid": 3062478078725637
+ },
+ {
+ "sitegoodsstockid": 3062468258188741
+ },
+ {
+ "sitegoodsstockid": 3062467463220741
+ },
+ {
+ "sitegoodsstockid": 3062461794897541
+ },
+ {
+ "sitegoodsstockid": 3062461795356293
+ },
+ {
+ "sitegoodsstockid": 3062449881189957
+ },
+ {
+ "sitegoodsstockid": 3062440914800197
+ },
+ {
+ "sitegoodsstockid": 3062440245350021
+ },
+ {
+ "sitegoodsstockid": 3062438795087365
+ },
+ {
+ "sitegoodsstockid": 3062437364174277
+ },
+ {
+ "sitegoodsstockid": 3062437363682757
+ },
+ {
+ "sitegoodsstockid": 3062436923870789
+ },
+ {
+ "sitegoodsstockid": 3062436924345925
+ },
+ {
+ "sitegoodsstockid": 3062414559350405
+ },
+ {
+ "sitegoodsstockid": 3062408446824005
+ },
+ {
+ "sitegoodsstockid": 3062406362369669
+ },
+ {
+ "sitegoodsstockid": 3062406361796229
+ },
+ {
+ "sitegoodsstockid": 3062405858823813
+ },
+ {
+ "sitegoodsstockid": 3062404478406085
+ },
+ {
+ "sitegoodsstockid": 3062402462993733
+ },
+ {
+ "sitegoodsstockid": 3062402462944581
+ },
+ {
+ "sitegoodsstockid": 3062378673589830
+ },
+ {
+ "sitegoodsstockid": 3062378457992773
+ },
+ {
+ "sitegoodsstockid": 3062378458975813
+ },
+ {
+ "sitegoodsstockid": 3062378455584325
+ },
+ {
+ "sitegoodsstockid": 3062378456043077
+ },
+ {
+ "sitegoodsstockid": 3062378456501829
+ },
+ {
+ "sitegoodsstockid": 3062378458467909
+ },
+ {
+ "sitegoodsstockid": 3062378456993349
+ },
+ {
+ "sitegoodsstockid": 3062378457517637
+ },
+ {
+ "sitegoodsstockid": 3062377537408453
+ },
+ {
+ "sitegoodsstockid": 3062377538407877
+ },
+ {
+ "sitegoodsstockid": 3062377538883013
+ },
+ {
+ "sitegoodsstockid": 3062377537916357
+ },
+ {
+ "sitegoodsstockid": 3062377533279685
+ },
+ {
+ "sitegoodsstockid": 3062377535376837
+ },
+ {
+ "sitegoodsstockid": 3062377536884165
+ },
+ {
+ "sitegoodsstockid": 3062377531182533
+ },
+ {
+ "sitegoodsstockid": 3062377531706821
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1706,
+ "records_with_pk": 1706,
+ "missing": 43,
+ "missing_samples": [
+ {
+ "id": 3062647002975685
+ },
+ {
+ "id": 3062626332675717
+ },
+ {
+ "id": 3062602558705221
+ },
+ {
+ "id": 3062466859535813
+ },
+ {
+ "id": 3062459259276869
+ },
+ {
+ "id": 3062367290527301
+ },
+ {
+ "id": 3062166829108805
+ },
+ {
+ "id": 3061791040327301
+ },
+ {
+ "id": 3061789721038469
+ },
+ {
+ "id": 3061771967483461
+ },
+ {
+ "id": 3061771967434309
+ },
+ {
+ "id": 3061740151590405
+ },
+ {
+ "id": 3061429638532613
+ },
+ {
+ "id": 3061429638499845
+ },
+ {
+ "id": 3061293033131525
+ },
+ {
+ "id": 3061293033082373
+ },
+ {
+ "id": 3061289629748805
+ },
+ {
+ "id": 3061266851810757
+ },
+ {
+ "id": 3061242697977349
+ },
+ {
+ "id": 3061241140039301
+ },
+ {
+ "id": 3061167280197189
+ },
+ {
+ "id": 3061069811256965
+ },
+ {
+ "id": 3061068943494789
+ },
+ {
+ "id": 3061068785127045
+ },
+ {
+ "id": 3060991466933893
+ },
+ {
+ "id": 3060990460775877
+ },
+ {
+ "id": 3060942519356869
+ },
+ {
+ "id": 3060695893296901
+ },
+ {
+ "id": 3060106497968965
+ },
+ {
+ "id": 3060091174046533
+ },
+ {
+ "id": 3060087559310149
+ },
+ {
+ "id": 3060087559277381
+ },
+ {
+ "id": 3060009548712965
+ },
+ {
+ "id": 3060006939020101
+ },
+ {
+ "id": 3059973952031749
+ },
+ {
+ "id": 3059966571449157
+ },
+ {
+ "id": 3059928272456517
+ },
+ {
+ "id": 3059879159171909
+ },
+ {
+ "id": 3059846913362949
+ },
+ {
+ "id": 3059762875698245
+ },
+ {
+ "id": 3059762000890693
+ },
+ {
+ "id": 3059699170266053
+ },
+ {
+ "id": 3059485872359109
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 643,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 643,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 723,
+ "total_errors": 0,
+ "generated_at": "2026-01-22T23:55:35.255726+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22929,
+ "ods": 22929,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22929,
+ "ods": 22929,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 563,
+ "ods": 563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 15302.94,
+ "ods_sum": 15302.94,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 28317.38,
+ "ods_sum": 28317.38,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 77583.17,
+ "ods_sum": 77583.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1801.23,
+ "ods_sum": 1801.23,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 33923.94,
+ "ods_sum": 33923.94,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17991,
+ "ods": 17991,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 315562.38,
+ "ods_sum": 315562.38,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2736,
+ "ods": 2736,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 89,
+ "ods": 158,
+ "diff": -69
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 191.21,
+ "diff": -191.21
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 33071.84,
+ "ods_sum": 58101.87,
+ "diff": -25030.030000000006
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4883,
+ "ods": 4883,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4677,
+ "ods": 4677,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4677,
+ "ods": 4677,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 227,
+ "ods": 227,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 15374.0,
+ "ods_sum": 15374.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 14729.3,
+ "ods_sum": 14729.3,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 10945,
+ "ods": 10945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7353.59,
+ "ods_sum": 7353.59,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 425,
+ "ods": 425,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 28900.0,
+ "ods_sum": 28900.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16707,
+ "ods": 16707,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 642,
+ "ods": 642,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 103410.0,
+ "ods_sum": 103410.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -2.0,
+ "ods_sum": -2.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 44,
+ "ods": 44,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -69
+ },
+ "generated_at": "2026-01-22T23:55:40.938507+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 723,
+ "total_errors": 0
+ },
+ "total_missing": 723,
+ "total_errors": 0,
+ "generated_at": "2026-01-22T23:55:40.938532+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260124_221448.json b/etl_billiards/reports/data_integrity_window_20260124_221448.json
new file mode 100644
index 0000000..73bf945
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260124_221448.json
@@ -0,0 +1,968 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/PersonnelManagement/SearchAssistantInfo"
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetAllOrderSettleList"
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetSiteTableOrderDetails"
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/AssistantPerformance/GetOrderAssistantDetails"
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/AssistantPerformance/GetAbolitionAssistant"
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsSalesList"
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/PayLog/GetPayLogListPage"
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Order/GetRefundPayLogList"
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Promotion/GetOfflineCouponConsumePageList"
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/MemberProfile/GetTenantMemberList"
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/MemberProfile/GetTenantMemberCardList"
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/MemberProfile/GetMemberCardBalanceChange"
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetRechargeSettleList"
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/PackageCoupon/QueryPackageCouponList"
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetSiteTableUseDetails"
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsStockReport"
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/GoodsStockManage/QueryGoodsOutboundReceipt"
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Table/GetSiteTables"
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoodsCategory/QueryPrimarySecondaryCategory"
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsInventoryList"
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetTaiFeeAdjustList"
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/QueryTenantGoods"
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 401 Client Error: Unauthorized for url: https://pc.ficoo.vip/apiprod/admin/v1/PayLog/GetPayLogListPage",
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 23,
+ "generated_at": "2026-01-24T22:14:42.999090+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22929,
+ "ods": 22929,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 22929,
+ "ods": 22929,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 358,
+ "ods": 358,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 10139.37,
+ "ods_sum": 10139.37,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 17057.33,
+ "ods_sum": 17057.33,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 52686.58,
+ "ods_sum": 52686.58,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1171.63,
+ "ods_sum": 1171.63,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 24821.37,
+ "ods_sum": 24821.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17992,
+ "ods": 17992,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2779,
+ "ods": 2779,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 323227.69,
+ "ods_sum": 323227.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2779,
+ "ods": 2779,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 37,
+ "ods": 106,
+ "diff": -69
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 191.21,
+ "diff": -191.21
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 12505.5,
+ "ods_sum": 37535.53,
+ "diff": -25030.03
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4883,
+ "ods": 4883,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4677,
+ "ods": 4677,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4677,
+ "ods": 4677,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 266,
+ "ods": 266,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 18240.0,
+ "ods_sum": 18240.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17057.33,
+ "ods_sum": 17057.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11157,
+ "ods": 11157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 259,
+ "ods": 259,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 17394.0,
+ "ods_sum": 17394.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16707,
+ "ods": 16707,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 407,
+ "ods": 407,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 80965.0,
+ "ods_sum": 80965.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 1,
+ "ods": 1,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -2.0,
+ "ods_sum": -2.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 44,
+ "ods": 44,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -69
+ },
+ "generated_at": "2026-01-24T22:14:48.193821+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 0,
+ "total_errors": 23
+ },
+ "total_missing": 0,
+ "total_errors": 23,
+ "generated_at": "2026-01-24T22:14:48.193853+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260124_222607.json b/etl_billiards/reports/data_integrity_window_20260124_222607.json
new file mode 100644
index 0000000..9014414
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260124_222607.json
@@ -0,0 +1,1400 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-19T19:14:15+08:00",
+ "end": "2026-01-25T00:14:15+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 647,
+ "records_with_pk": 647,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3065432416570181
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10037,
+ "records_with_pk": 10037,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 179,
+ "records_with_pk": 179,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11897,
+ "records_with_pk": 11897,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3065432435575685
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16861,
+ "records_with_pk": 16861,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3065433115265989
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 555,
+ "records_with_pk": 555,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 944,
+ "records_with_pk": 944,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8253,
+ "records_with_pk": 8253,
+ "missing": 147,
+ "missing_samples": [
+ {
+ "id": 3065424093170565
+ },
+ {
+ "id": 3065417916025669
+ },
+ {
+ "id": 3065416799013701
+ },
+ {
+ "id": 3065412410543045
+ },
+ {
+ "id": 3065410940308293
+ },
+ {
+ "id": 3065410940308294
+ },
+ {
+ "id": 3065402568903621
+ },
+ {
+ "id": 3065400934321093
+ },
+ {
+ "id": 3065400878271301
+ },
+ {
+ "id": 3065400878287685
+ },
+ {
+ "id": 3065392583019397
+ },
+ {
+ "id": 3065392512322501
+ },
+ {
+ "id": 3065389440453573
+ },
+ {
+ "id": 3065389440453574
+ },
+ {
+ "id": 3065384249494341
+ },
+ {
+ "id": 3065379691055941
+ },
+ {
+ "id": 3065373443803973
+ },
+ {
+ "id": 3065373139897541
+ },
+ {
+ "id": 3065358031375301
+ },
+ {
+ "id": 3065355638344517
+ },
+ {
+ "id": 3065349042424773
+ },
+ {
+ "id": 3065346835385285
+ },
+ {
+ "id": 3065320965507973
+ },
+ {
+ "id": 3065307692174277
+ },
+ {
+ "id": 3065304304421765
+ },
+ {
+ "id": 3065304304421766
+ },
+ {
+ "id": 3065284099279813
+ },
+ {
+ "id": 3065274420841285
+ },
+ {
+ "id": 3065259484433606
+ },
+ {
+ "id": 3065250665761989
+ },
+ {
+ "id": 3065245825715141
+ },
+ {
+ "id": 3065225740176197
+ },
+ {
+ "id": 3065210599214021
+ },
+ {
+ "id": 3065203094653829
+ },
+ {
+ "id": 3065199175404357
+ },
+ {
+ "id": 3065185918520134
+ },
+ {
+ "id": 3065184442436549
+ },
+ {
+ "id": 3065182172924805
+ },
+ {
+ "id": 3065177155554245
+ },
+ {
+ "id": 3065177155554246
+ },
+ {
+ "id": 3065160959527813
+ },
+ {
+ "id": 3065093558455109
+ },
+ {
+ "id": 3065077314112325
+ },
+ {
+ "id": 3065077314112326
+ },
+ {
+ "id": 3065069899680965
+ },
+ {
+ "id": 3065054093741253
+ },
+ {
+ "id": 3065054039657413
+ },
+ {
+ "id": 3065053956721477
+ },
+ {
+ "id": 3065024393562949
+ },
+ {
+ "id": 3065020157463365
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1004,
+ "records_with_pk": 1004,
+ "missing": 430,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3065245741796549
+ },
+ {
+ "sitegoodsstockid": 3065241888689029
+ },
+ {
+ "sitegoodsstockid": 3065230523976517
+ },
+ {
+ "sitegoodsstockid": 3065228210048197
+ },
+ {
+ "sitegoodsstockid": 3065228210244805
+ },
+ {
+ "sitegoodsstockid": 3065223410305925
+ },
+ {
+ "sitegoodsstockid": 3065222393892037
+ },
+ {
+ "sitegoodsstockid": 3065222257380229
+ },
+ {
+ "sitegoodsstockid": 3065211575290757
+ },
+ {
+ "sitegoodsstockid": 3065208430349509
+ },
+ {
+ "sitegoodsstockid": 3065208430972101
+ },
+ {
+ "sitegoodsstockid": 3065202672733061
+ },
+ {
+ "sitegoodsstockid": 3065202672569221
+ },
+ {
+ "sitegoodsstockid": 3065192541162693
+ },
+ {
+ "sitegoodsstockid": 3065184738905029
+ },
+ {
+ "sitegoodsstockid": 3065183562517445
+ },
+ {
+ "sitegoodsstockid": 3065179536886981
+ },
+ {
+ "sitegoodsstockid": 3065177298717893
+ },
+ {
+ "sitegoodsstockid": 3065174962277317
+ },
+ {
+ "sitegoodsstockid": 3065174340258693
+ },
+ {
+ "sitegoodsstockid": 3065169942875077
+ },
+ {
+ "sitegoodsstockid": 3065169942399941
+ },
+ {
+ "sitegoodsstockid": 3065165534743429
+ },
+ {
+ "sitegoodsstockid": 3065161782332357
+ },
+ {
+ "sitegoodsstockid": 3065152084118725
+ },
+ {
+ "sitegoodsstockid": 3065146629835589
+ },
+ {
+ "sitegoodsstockid": 3065145603378373
+ },
+ {
+ "sitegoodsstockid": 3065144114351301
+ },
+ {
+ "sitegoodsstockid": 3065143976283077
+ },
+ {
+ "sitegoodsstockid": 3065142173993925
+ },
+ {
+ "sitegoodsstockid": 3065132596923205
+ },
+ {
+ "sitegoodsstockid": 3065131517791045
+ },
+ {
+ "sitegoodsstockid": 3065131443555269
+ },
+ {
+ "sitegoodsstockid": 3065131001809861
+ },
+ {
+ "sitegoodsstockid": 3065128696630149
+ },
+ {
+ "sitegoodsstockid": 3065117668412613
+ },
+ {
+ "sitegoodsstockid": 3065115329662149
+ },
+ {
+ "sitegoodsstockid": 3065109122304837
+ },
+ {
+ "sitegoodsstockid": 3065106178493637
+ },
+ {
+ "sitegoodsstockid": 3065093014571845
+ },
+ {
+ "sitegoodsstockid": 3065091746991045
+ },
+ {
+ "sitegoodsstockid": 3065091647278277
+ },
+ {
+ "sitegoodsstockid": 3065090336164805
+ },
+ {
+ "sitegoodsstockid": 3065090335689669
+ },
+ {
+ "sitegoodsstockid": 3065089641745605
+ },
+ {
+ "sitegoodsstockid": 3065089496714053
+ },
+ {
+ "sitegoodsstockid": 3065088993397701
+ },
+ {
+ "sitegoodsstockid": 3065088993889221
+ },
+ {
+ "sitegoodsstockid": 3065087358733509
+ },
+ {
+ "sitegoodsstockid": 3065041513286533
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1721,
+ "records_with_pk": 1721,
+ "missing": 39,
+ "missing_samples": [
+ {
+ "id": 3065324486544325
+ },
+ {
+ "id": 3065324486511557
+ },
+ {
+ "id": 3065281420757957
+ },
+ {
+ "id": 3065225880865605
+ },
+ {
+ "id": 3065110094334789
+ },
+ {
+ "id": 3064404466191301
+ },
+ {
+ "id": 3064402686987077
+ },
+ {
+ "id": 3064262805179333
+ },
+ {
+ "id": 3064246571944837
+ },
+ {
+ "id": 3064245835828165
+ },
+ {
+ "id": 3064245835779013
+ },
+ {
+ "id": 3064244105513925
+ },
+ {
+ "id": 3064244105563077
+ },
+ {
+ "id": 3064241885105093
+ },
+ {
+ "id": 3064228079962949
+ },
+ {
+ "id": 3064218902219973
+ },
+ {
+ "id": 3064218046385349
+ },
+ {
+ "id": 3064178963942213
+ },
+ {
+ "id": 3064174046317509
+ },
+ {
+ "id": 3064172743216069
+ },
+ {
+ "id": 3064169279654853
+ },
+ {
+ "id": 3064159579278213
+ },
+ {
+ "id": 3064148606159813
+ },
+ {
+ "id": 3064120615963845
+ },
+ {
+ "id": 3064102418533317
+ },
+ {
+ "id": 3064074573908933
+ },
+ {
+ "id": 3064074573876165
+ },
+ {
+ "id": 3064035698887877
+ },
+ {
+ "id": 3064031616895813
+ },
+ {
+ "id": 3063961039850373
+ },
+ {
+ "id": 3063790926089093
+ },
+ {
+ "id": 3062937796758981
+ },
+ {
+ "id": 3062937039163013
+ },
+ {
+ "id": 3062937039195781
+ },
+ {
+ "id": 3062882662944261
+ },
+ {
+ "id": 3062728738557573
+ },
+ {
+ "id": 3062704209858117
+ },
+ {
+ "id": 3062703566769669
+ },
+ {
+ "id": 3062703566884358
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 664,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 664,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 619,
+ "total_errors": 0,
+ "generated_at": "2026-01-24T22:26:02.533790+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23183,
+ "ods": 23183,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23183,
+ "ods": 23183,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 589,
+ "ods": 589,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 13116.82,
+ "ods_sum": 13116.82,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 26829.58,
+ "ods_sum": 26829.58,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 76782.02,
+ "ods_sum": 76782.02,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 2118.18,
+ "ods_sum": 2118.18,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 35220.56,
+ "ods_sum": 35220.56,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18223,
+ "ods": 18223,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2779,
+ "ods": 2779,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 323227.69,
+ "ods_sum": 323227.69,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2779,
+ "ods": 2779,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 37,
+ "ods": 179,
+ "diff": -142
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 191.21,
+ "diff": -191.21
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 12505.5,
+ "ods_sum": 52789.73,
+ "diff": -40284.23
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4956,
+ "ods": 4956,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 97,
+ "ods": 97,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4709,
+ "ods": 4709,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4709,
+ "ods": 4709,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 266,
+ "ods": 266,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 18240.0,
+ "ods_sum": 18240.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 17057.33,
+ "ods_sum": 17057.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11157,
+ "ods": 11157,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 412,
+ "ods": 412,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 27944.0,
+ "ods_sum": 27944.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16860,
+ "ods": 16860,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 453,
+ "ods": 453,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 662,
+ "ods": 662,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 99285.0,
+ "ods_sum": 99285.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -142
+ },
+ "generated_at": "2026-01-24T22:26:07.565369+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 619,
+ "total_errors": 0
+ },
+ "total_missing": 619,
+ "total_errors": 0,
+ "generated_at": "2026-01-24T22:26:07.565393+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260125_205910.json b/etl_billiards/reports/data_integrity_window_20260125_205910.json
new file mode 100644
index 0000000..d5675ec
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260125_205910.json
@@ -0,0 +1,1340 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-20T17:48:03+08:00",
+ "end": "2026-01-25T22:48:03+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-20T17:48:03+08:00",
+ "end": "2026-01-25T22:48:03+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-20T17:48:03+08:00",
+ "end": "2026-01-25T22:48:03+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 646,
+ "records_with_pk": 646,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3066762932817093
+ },
+ {
+ "id": 3066762524838789
+ }
+ ],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10026,
+ "records_with_pk": 10026,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066762567027909
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 165,
+ "records_with_pk": 165,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066762981362565
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11875,
+ "records_with_pk": 11875,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3066762977905541
+ },
+ {
+ "id": 3066762563636421
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16928,
+ "records_with_pk": 16928,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066764959435717
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 555,
+ "records_with_pk": 555,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 944,
+ "records_with_pk": 944,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2461,
+ "records_with_pk": 2461,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066762978577285
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8235,
+ "records_with_pk": 8235,
+ "missing": 72,
+ "missing_samples": [
+ {
+ "id": 3066765213338565
+ },
+ {
+ "id": 3066744119905221
+ },
+ {
+ "id": 3066743229713349
+ },
+ {
+ "id": 3066743163702213
+ },
+ {
+ "id": 3066733825526981
+ },
+ {
+ "id": 3066729700838277
+ },
+ {
+ "id": 3066724925148357
+ },
+ {
+ "id": 3066699462102213
+ },
+ {
+ "id": 3066695991675781
+ },
+ {
+ "id": 3066664761166725
+ },
+ {
+ "id": 3066660179676357
+ },
+ {
+ "id": 3066609163701189
+ },
+ {
+ "id": 3066599204965255
+ },
+ {
+ "id": 3066599204965254
+ },
+ {
+ "id": 3066599204948870
+ },
+ {
+ "id": 3066594442726213
+ },
+ {
+ "id": 3066590040460165
+ },
+ {
+ "id": 3066588205042885
+ },
+ {
+ "id": 3066579501255621
+ },
+ {
+ "id": 3066569299839877
+ },
+ {
+ "id": 3066563042282693
+ },
+ {
+ "id": 3066563042266309
+ },
+ {
+ "id": 3066556331068293
+ },
+ {
+ "id": 3066549868645253
+ },
+ {
+ "id": 3066549815610309
+ },
+ {
+ "id": 3066546409098181
+ },
+ {
+ "id": 3066542941932485
+ },
+ {
+ "id": 3066532562734021
+ },
+ {
+ "id": 3066532497132357
+ },
+ {
+ "id": 3066532427795269
+ },
+ {
+ "id": 3066524469234885
+ },
+ {
+ "id": 3066522309004101
+ },
+ {
+ "id": 3066522236439493
+ },
+ {
+ "id": 3066515036638405
+ },
+ {
+ "id": 3066511403470021
+ },
+ {
+ "id": 3066496075418437
+ },
+ {
+ "id": 3066496030706501
+ },
+ {
+ "id": 3066495904828357
+ },
+ {
+ "id": 3066476092574917
+ },
+ {
+ "id": 3066474454715269
+ },
+ {
+ "id": 3066462069410693
+ },
+ {
+ "id": 3066455198337989
+ },
+ {
+ "id": 3066450071472965
+ },
+ {
+ "id": 3066409219984261
+ },
+ {
+ "id": 3066405355277190
+ },
+ {
+ "id": 3066405355277189
+ },
+ {
+ "id": 3066395040517317
+ },
+ {
+ "id": 3066363220659142
+ },
+ {
+ "id": 3066363220659141
+ },
+ {
+ "id": 3066265725275333
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1140,
+ "records_with_pk": 1140,
+ "missing": 250,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3066571175840645
+ },
+ {
+ "sitegoodsstockid": 3066571175660422
+ },
+ {
+ "sitegoodsstockid": 3066568978566021
+ },
+ {
+ "sitegoodsstockid": 3066566739331973
+ },
+ {
+ "sitegoodsstockid": 3066561612450757
+ },
+ {
+ "sitegoodsstockid": 3066527975394501
+ },
+ {
+ "sitegoodsstockid": 3066469781130181
+ },
+ {
+ "sitegoodsstockid": 3066467383577541
+ },
+ {
+ "sitegoodsstockid": 3066461893299013
+ },
+ {
+ "sitegoodsstockid": 3066459622935365
+ },
+ {
+ "sitegoodsstockid": 3066459623377733
+ },
+ {
+ "sitegoodsstockid": 3066458632883397
+ },
+ {
+ "sitegoodsstockid": 3066456988879813
+ },
+ {
+ "sitegoodsstockid": 3066414782843781
+ },
+ {
+ "sitegoodsstockid": 3066352712026949
+ },
+ {
+ "sitegoodsstockid": 3066352378252165
+ },
+ {
+ "sitegoodsstockid": 3066275859565189
+ },
+ {
+ "sitegoodsstockid": 3066275859630725
+ },
+ {
+ "sitegoodsstockid": 3066170776685445
+ },
+ {
+ "sitegoodsstockid": 3066150230412485
+ },
+ {
+ "sitegoodsstockid": 3066149619551173
+ },
+ {
+ "sitegoodsstockid": 3066145925696709
+ },
+ {
+ "sitegoodsstockid": 3066145525861253
+ },
+ {
+ "sitegoodsstockid": 3066145449331589
+ },
+ {
+ "sitegoodsstockid": 3066145243384709
+ },
+ {
+ "sitegoodsstockid": 3066145101352133
+ },
+ {
+ "sitegoodsstockid": 3066124677335877
+ },
+ {
+ "sitegoodsstockid": 3066111808900037
+ },
+ {
+ "sitegoodsstockid": 3066111808424901
+ },
+ {
+ "sitegoodsstockid": 3066025951775941
+ },
+ {
+ "sitegoodsstockid": 3065993567554437
+ },
+ {
+ "sitegoodsstockid": 3065898516040901
+ },
+ {
+ "sitegoodsstockid": 3065885509881029
+ },
+ {
+ "sitegoodsstockid": 3065885509438661
+ },
+ {
+ "sitegoodsstockid": 3065865922431941
+ },
+ {
+ "sitegoodsstockid": 3065840807447365
+ },
+ {
+ "sitegoodsstockid": 3065833098480453
+ },
+ {
+ "sitegoodsstockid": 3065828643900613
+ },
+ {
+ "sitegoodsstockid": 3065827552365765
+ },
+ {
+ "sitegoodsstockid": 3065827308571525
+ },
+ {
+ "sitegoodsstockid": 3065827309030277
+ },
+ {
+ "sitegoodsstockid": 3065810108943557
+ },
+ {
+ "sitegoodsstockid": 3065810108452037
+ },
+ {
+ "sitegoodsstockid": 3065807975353541
+ },
+ {
+ "sitegoodsstockid": 3065807974878405
+ },
+ {
+ "sitegoodsstockid": 3065803975838533
+ },
+ {
+ "sitegoodsstockid": 3065803976313669
+ },
+ {
+ "sitegoodsstockid": 3065768815758533
+ },
+ {
+ "sitegoodsstockid": 3065768674052997
+ },
+ {
+ "sitegoodsstockid": 3065745743629189
+ }
+ ],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1726,
+ "records_with_pk": 1726,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3066762568813765
+ },
+ {
+ "id": 3066756388457285
+ },
+ {
+ "id": 3066544822193093
+ },
+ {
+ "id": 3065836342545605
+ },
+ {
+ "id": 3065836342496453
+ },
+ {
+ "id": 3065836342463685
+ },
+ {
+ "id": 3065692712897413
+ },
+ {
+ "id": 3065691637091205
+ },
+ {
+ "id": 3065652223020229
+ },
+ {
+ "id": 3065628579040197
+ },
+ {
+ "id": 3065599311104965
+ },
+ {
+ "id": 3065571314518917
+ },
+ {
+ "id": 3065525921500357
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 663,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 663,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 343,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T20:59:04.867283+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23287,
+ "ods": 23287,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23287,
+ "ods": 23287,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 589,
+ "ods": 589,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 11951.42,
+ "ods_sum": 11951.42,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 28028.05,
+ "ods_sum": 28028.05,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 76366.69,
+ "ods_sum": 76366.69,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 2137.43,
+ "ods_sum": 2137.43,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 34249.79,
+ "ods_sum": 34249.79,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18316,
+ "ods": 18316,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2821,
+ "ods": 2821,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 326488.63,
+ "ods_sum": 326488.63,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2821,
+ "ods": 2821,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 164,
+ "diff": -164
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 191.21,
+ "diff": -191.21
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 48407.44,
+ "diff": -48407.44
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4979,
+ "ods": 4979,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4723,
+ "ods": 4723,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4723,
+ "ods": 4723,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 356,
+ "ods": 356,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 24486.0,
+ "ods_sum": 24486.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 23234.33,
+ "ods_sum": 23234.33,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11308,
+ "ods": 11308,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 420,
+ "ods": 420,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 28754.0,
+ "ods_sum": 28754.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16927,
+ "ods": 16927,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 658,
+ "ods": 658,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 90429.0,
+ "ods_sum": 90429.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -164
+ },
+ "generated_at": "2026-01-25T20:59:10.890641+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 343,
+ "total_errors": 0
+ },
+ "total_missing": 343,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T20:59:10.890662+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260125_213632.json b/etl_billiards/reports/data_integrity_window_20260125_213632.json
new file mode 100644
index 0000000..1874e49
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260125_213632.json
@@ -0,0 +1,1012 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-20T18:25:39+08:00",
+ "end": "2026-01-25T23:25:39+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-20T18:25:39+08:00",
+ "end": "2026-01-25T23:25:39+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-20T18:25:39+08:00",
+ "end": "2026-01-25T23:25:39+08:00",
+ "cutoff": null,
+ "window_days": 5,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 647,
+ "records_with_pk": 647,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10038,
+ "records_with_pk": 10038,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11886,
+ "records_with_pk": 11886,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066800435252037
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16936,
+ "records_with_pk": 16936,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066801278192581
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2467,
+ "records_with_pk": 2467,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8239,
+ "records_with_pk": 8239,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3066800440560453
+ },
+ {
+ "id": 3066788584541381
+ },
+ {
+ "id": 3066788515990405
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1143,
+ "records_with_pk": 1143,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3066803443321797
+ },
+ {
+ "sitegoodsstockid": 3066801536994117
+ },
+ {
+ "sitegoodsstockid": 3066787800599749
+ },
+ {
+ "sitegoodsstockid": 3066783702698949
+ },
+ {
+ "sitegoodsstockid": 3066783371676549
+ },
+ {
+ "sitegoodsstockid": 3066782126034117
+ },
+ {
+ "sitegoodsstockid": 3066765352488133
+ }
+ ],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1728,
+ "records_with_pk": 1728,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066779332676421
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 663,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 663,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T21:36:26.575196+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23298,
+ "ods": 23298,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23298,
+ "ods": 23298,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 594,
+ "ods": 594,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 12599.72,
+ "ods_sum": 12599.72,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 28002.09,
+ "ods_sum": 28002.09,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 78280.35,
+ "ods_sum": 78280.35,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 2279.12,
+ "ods_sum": 2279.12,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 35399.42,
+ "ods_sum": 35399.42,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18328,
+ "ods": 18328,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2835,
+ "ods": 2835,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328170.71,
+ "ods_sum": 328170.71,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2835,
+ "ods": 2835,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 172,
+ "diff": -172
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 191.21,
+ "diff": -191.21
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 50571.78,
+ "diff": -50571.78
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4987,
+ "ods": 4987,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4730,
+ "ods": 4730,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4730,
+ "ods": 4730,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 425,
+ "ods": 425,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 29138.0,
+ "ods_sum": 29138.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 27858.09,
+ "ods_sum": 27858.09,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11381,
+ "ods": 11381,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 425,
+ "ods": 425,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 29160.0,
+ "ods_sum": 29160.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16935,
+ "ods": 16935,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 662,
+ "ods": 662,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 90926.0,
+ "ods_sum": 90926.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 2,
+ "ods": 2,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -7.0,
+ "ods_sum": -7.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -172
+ },
+ "generated_at": "2026-01-25T21:36:32.441421+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 13,
+ "total_errors": 0
+ },
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T21:36:32.441443+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260125_224002.json b/etl_billiards/reports/data_integrity_window_20260125_224002.json
new file mode 100644
index 0000000..f7c3a14
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260125_224002.json
@@ -0,0 +1,1066 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-25T14:29:34+08:00",
+ "end": "2026-01-26T00:29:34+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-25T14:29:34+08:00",
+ "end": "2026-01-26T00:29:34+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-25T14:29:34+08:00",
+ "end": "2026-01-26T00:29:34+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 10,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 68,
+ "records_with_pk": 68,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 76,
+ "records_with_pk": 76,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066860365499269
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10044,
+ "records_with_pk": 10044,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066860419124165
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11895,
+ "records_with_pk": 11895,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066860416289733
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16944,
+ "records_with_pk": 16944,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3066861558500549
+ },
+ {
+ "id": 3066861405555589
+ }
+ ],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2471,
+ "records_with_pk": 2471,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066860416912325
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8243,
+ "records_with_pk": 8243,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3066837878312133
+ },
+ {
+ "id": 3066837374143365
+ },
+ {
+ "id": 3066833646750661
+ },
+ {
+ "id": 3066828194647237
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 59,
+ "records_with_pk": 59,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3066865924524997
+ },
+ {
+ "sitegoodsstockid": 3066863944010629
+ },
+ {
+ "sitegoodsstockid": 3066862740032389
+ },
+ {
+ "sitegoodsstockid": 3066858755050309
+ },
+ {
+ "sitegoodsstockid": 3066840188848965
+ },
+ {
+ "sitegoodsstockid": 3066838289435525
+ },
+ {
+ "sitegoodsstockid": 3066835140692933
+ },
+ {
+ "sitegoodsstockid": 3066833444015045
+ },
+ {
+ "sitegoodsstockid": 3066831699168197
+ },
+ {
+ "sitegoodsstockid": 3066826001795973
+ },
+ {
+ "sitegoodsstockid": 3066824803208133
+ },
+ {
+ "sitegoodsstockid": 3066821797711045
+ },
+ {
+ "sitegoodsstockid": 3066821798251717
+ },
+ {
+ "sitegoodsstockid": 3066821798759622
+ },
+ {
+ "sitegoodsstockid": 3066814938450885
+ },
+ {
+ "sitegoodsstockid": 3066814509944005
+ },
+ {
+ "sitegoodsstockid": 3066813892185285
+ },
+ {
+ "sitegoodsstockid": 3066803443321797
+ },
+ {
+ "sitegoodsstockid": 3066801536994117
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1729,
+ "records_with_pk": 1729,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3066860419976133
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 77,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 77,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 30,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T22:39:57.506027+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23307,
+ "ods": 23307,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23307,
+ "ods": 23307,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 68,
+ "ods": 68,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 841.32,
+ "ods_sum": 841.32,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 3595.19,
+ "ods_sum": 3595.19,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 7205.11,
+ "ods_sum": 7205.11,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 412.5,
+ "ods_sum": 412.5,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 2356.1,
+ "ods_sum": 2356.1,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18334,
+ "ods": 18334,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2836,
+ "ods": 2836,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328238.71,
+ "ods_sum": 328238.71,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2836,
+ "ods": 2836,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 10,
+ "ods": 10,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 3280.45,
+ "ods_sum": 3280.45,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4988,
+ "ods": 4988,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4733,
+ "ods": 4733,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4733,
+ "ods": 4733,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 51,
+ "ods": 51,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 3436.0,
+ "ods_sum": 3436.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 3403.19,
+ "ods_sum": 3403.19,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11384,
+ "ods": 11384,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 58,
+ "ods": 58,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 3978.0,
+ "ods_sum": 3978.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16942,
+ "ods": 16942,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 76,
+ "ods": 76,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 1600.0,
+ "ods_sum": 1600.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 0
+ },
+ "generated_at": "2026-01-25T22:40:02.547821+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 30,
+ "total_errors": 0
+ },
+ "total_missing": 30,
+ "total_errors": 0,
+ "generated_at": "2026-01-25T22:40:02.547851+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260126_033329.json b/etl_billiards/reports/data_integrity_window_20260126_033329.json
new file mode 100644
index 0000000..20c1f27
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260126_033329.json
@@ -0,0 +1,1196 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-25T00:22:48+08:00",
+ "end": "2026-01-26T05:22:48+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-25T00:22:48+08:00",
+ "end": "2026-01-26T05:22:48+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-25T00:22:48+08:00",
+ "end": "2026-01-26T05:22:48+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 134,
+ "records_with_pk": 134,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10070,
+ "records_with_pk": 10070,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 40,
+ "records_with_pk": 40,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11926,
+ "records_with_pk": 11926,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2472,
+ "records_with_pk": 2472,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 23,
+ "missing_samples": [
+ {
+ "id": 3067007305763654
+ },
+ {
+ "id": 3067007305763653
+ },
+ {
+ "id": 3067007245962181
+ },
+ {
+ "id": 3067007177264326
+ },
+ {
+ "id": 3067007177264325
+ },
+ {
+ "id": 3066996143246533
+ },
+ {
+ "id": 3066991452015429
+ },
+ {
+ "id": 3066966237777093
+ },
+ {
+ "id": 3066966237760709
+ },
+ {
+ "id": 3066945936493445
+ },
+ {
+ "id": 3066945936477061
+ },
+ {
+ "id": 3066945882590405
+ },
+ {
+ "id": 3066934585723717
+ },
+ {
+ "id": 3066930340908230
+ },
+ {
+ "id": 3066930340908229
+ },
+ {
+ "id": 3066924696079301
+ },
+ {
+ "id": 3066911455546566
+ },
+ {
+ "id": 3066911455546565
+ },
+ {
+ "id": 3066899743165317
+ },
+ {
+ "id": 3066888588004549
+ },
+ {
+ "id": 3066884198206405
+ },
+ {
+ "id": 3066879329389766
+ },
+ {
+ "id": 3066879329389765
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 189,
+ "records_with_pk": 189,
+ "missing": 44,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3066966928165829
+ },
+ {
+ "sitegoodsstockid": 3066965057883013
+ },
+ {
+ "sitegoodsstockid": 3066963423939397
+ },
+ {
+ "sitegoodsstockid": 3066948529720197
+ },
+ {
+ "sitegoodsstockid": 3066934741797701
+ },
+ {
+ "sitegoodsstockid": 3066930778737541
+ },
+ {
+ "sitegoodsstockid": 3066930778131333
+ },
+ {
+ "sitegoodsstockid": 3066924912823173
+ },
+ {
+ "sitegoodsstockid": 3066924525898949
+ },
+ {
+ "sitegoodsstockid": 3066894414121861
+ },
+ {
+ "sitegoodsstockid": 3066893671451589
+ },
+ {
+ "sitegoodsstockid": 3066893434096581
+ },
+ {
+ "sitegoodsstockid": 3066893434653637
+ },
+ {
+ "sitegoodsstockid": 3066893033737029
+ },
+ {
+ "sitegoodsstockid": 3066891056286597
+ },
+ {
+ "sitegoodsstockid": 3066890729032581
+ },
+ {
+ "sitegoodsstockid": 3066879735975109
+ },
+ {
+ "sitegoodsstockid": 3066870537178309
+ },
+ {
+ "sitegoodsstockid": 3066865924524997
+ },
+ {
+ "sitegoodsstockid": 3066863944010629
+ },
+ {
+ "sitegoodsstockid": 3066862740032389
+ },
+ {
+ "sitegoodsstockid": 3066858755050309
+ },
+ {
+ "sitegoodsstockid": 3067131858913925
+ },
+ {
+ "sitegoodsstockid": 3067131687258821
+ },
+ {
+ "sitegoodsstockid": 3067131189348997
+ },
+ {
+ "sitegoodsstockid": 3067131189283461
+ },
+ {
+ "sitegoodsstockid": 3067101593095045
+ },
+ {
+ "sitegoodsstockid": 3067098731154245
+ },
+ {
+ "sitegoodsstockid": 3067098559007685
+ },
+ {
+ "sitegoodsstockid": 3067087092943813
+ },
+ {
+ "sitegoodsstockid": 3067084451679429
+ },
+ {
+ "sitegoodsstockid": 3067062820506501
+ },
+ {
+ "sitegoodsstockid": 3067062820014981
+ },
+ {
+ "sitegoodsstockid": 3067039710038981
+ },
+ {
+ "sitegoodsstockid": 3067038608526214
+ },
+ {
+ "sitegoodsstockid": 3067031433202885
+ },
+ {
+ "sitegoodsstockid": 3067031168044229
+ },
+ {
+ "sitegoodsstockid": 3067012409297733
+ },
+ {
+ "sitegoodsstockid": 3067003958938437
+ },
+ {
+ "sitegoodsstockid": 3066989658426565
+ },
+ {
+ "sitegoodsstockid": 3066989657918661
+ },
+ {
+ "sitegoodsstockid": 3066986650766277
+ },
+ {
+ "sitegoodsstockid": 3066971236223813
+ },
+ {
+ "sitegoodsstockid": 3066969598643141
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1737,
+ "records_with_pk": 1737,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3067055412218821
+ },
+ {
+ "id": 3067055412186053
+ },
+ {
+ "id": 3066988293721285
+ },
+ {
+ "id": 3066965660617605
+ },
+ {
+ "id": 3066964104792901
+ },
+ {
+ "id": 3066950943394757
+ },
+ {
+ "id": 3066915093728069
+ },
+ {
+ "id": 3066888849149125
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 136,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 136,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 75,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T03:33:24.462285+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 122,
+ "ods": 122,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 2342.95,
+ "ods_sum": 2342.95,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 5940.13,
+ "ods_sum": 5940.13,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 15271.95,
+ "ods_sum": 15271.95,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 412.5,
+ "ods_sum": 412.5,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 6576.37,
+ "ods_sum": 6576.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2837,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328358.71,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2837,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 40,
+ "ods": 40,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 13656.85,
+ "ods_sum": 13656.85,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 71,
+ "ods": 71,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 4540.0,
+ "ods_sum": 4540.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4504.13,
+ "ods_sum": 4504.13,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11388,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 81,
+ "ods": 81,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 5208.0,
+ "ods_sum": 5208.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 136,
+ "ods": 136,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 14159.0,
+ "ods_sum": 14159.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 0
+ },
+ "generated_at": "2026-01-26T03:33:29.767935+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 75,
+ "total_errors": 0
+ },
+ "total_missing": 75,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T03:33:29.767965+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260126_035534.json b/etl_billiards/reports/data_integrity_window_20260126_035534.json
new file mode 100644
index 0000000..1937659
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260126_035534.json
@@ -0,0 +1,972 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-24T00:45:10+08:00",
+ "end": "2026-01-26T05:45:10+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-24T00:45:10+08:00",
+ "end": "2026-01-26T05:45:10+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-24T00:45:10+08:00",
+ "end": "2026-01-26T05:45:10+08:00",
+ "cutoff": null,
+ "window_days": 2,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 136,
+ "records_with_pk": 136,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 284,
+ "records_with_pk": 284,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10070,
+ "records_with_pk": 10070,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 83,
+ "records_with_pk": 83,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11926,
+ "records_with_pk": 11926,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16953,
+ "records_with_pk": 16953,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2472,
+ "records_with_pk": 2472,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8266,
+ "records_with_pk": 8266,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 548,
+ "records_with_pk": 548,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3067169196329861
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1737,
+ "records_with_pk": 1737,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 286,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 286,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T03:55:28.356697+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23339,
+ "ods": 23339,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 254,
+ "ods": 254,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 4468.13,
+ "ods_sum": 4468.13,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 11343.14,
+ "ods_sum": 11343.14,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 29695.36,
+ "ods_sum": 29695.36,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 819.01,
+ "ods_sum": 819.01,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 13065.08,
+ "ods_sum": 13065.08,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18361,
+ "ods": 18361,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328358.71,
+ "ods_sum": 328901.21,
+ "diff": -542.5
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2837,
+ "ods": 2845,
+ "diff": -8
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 83,
+ "ods": 83,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 21036.95,
+ "ods_sum": 21036.95,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4998,
+ "ods": 4998,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4735,
+ "ods": 4735,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 146,
+ "ods": 169,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 10116.0,
+ "ods_sum": 11552.0,
+ "diff": -1436.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 9907.14,
+ "ods_sum": 11343.14,
+ "diff": -1436.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11388,
+ "ods": 11411,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 165,
+ "ods": 165,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 11216.0,
+ "ods_sum": 11216.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16953,
+ "ods": 16953,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 454,
+ "ods": 454,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 286,
+ "ods": 286,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 25812.0,
+ "ods_sum": 25812.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -62
+ },
+ "generated_at": "2026-01-26T03:55:34.698078+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 1,
+ "total_errors": 0
+ },
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T03:55:34.698101+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260126_182902.json b/etl_billiards/reports/data_integrity_window_20260126_182902.json
new file mode 100644
index 0000000..b82a0b3
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260126_182902.json
@@ -0,0 +1,1151 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-24T15:23:05+08:00",
+ "end": "2026-01-26T20:23:05+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-24T15:23:05+08:00",
+ "end": "2026-01-26T20:23:05+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-24T15:23:05+08:00",
+ "end": "2026-01-26T20:23:05+08:00",
+ "cutoff": null,
+ "window_days": 2,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 138,
+ "records_with_pk": 138,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 278,
+ "records_with_pk": 278,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9939,
+ "records_with_pk": 9939,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 70,
+ "records_with_pk": 70,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11770,
+ "records_with_pk": 11770,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16977,
+ "records_with_pk": 16977,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 85,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2460,
+ "records_with_pk": 2460,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8160,
+ "records_with_pk": 8160,
+ "missing": 16,
+ "missing_samples": [
+ {
+ "id": 3068019000723653
+ },
+ {
+ "id": 3067992374970501
+ },
+ {
+ "id": 3067985684777285
+ },
+ {
+ "id": 3067955077302405
+ },
+ {
+ "id": 3067912089471301
+ },
+ {
+ "id": 3067909312940229
+ },
+ {
+ "id": 3067891288460485
+ },
+ {
+ "id": 3067865836801221
+ },
+ {
+ "id": 3067865836801222
+ },
+ {
+ "id": 3067853161680069
+ },
+ {
+ "id": 3067840765987717
+ },
+ {
+ "id": 3067838769564485
+ },
+ {
+ "id": 3067838769564486
+ },
+ {
+ "id": 3067824960310085
+ },
+ {
+ "id": 3067817526774661
+ },
+ {
+ "id": 3067809982434501
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 488,
+ "records_with_pk": 488,
+ "missing": 40,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3067817042152389
+ },
+ {
+ "sitegoodsstockid": 3067811998468997
+ },
+ {
+ "sitegoodsstockid": 3067803612662661
+ },
+ {
+ "sitegoodsstockid": 3067800357997765
+ },
+ {
+ "sitegoodsstockid": 3067796231850885
+ },
+ {
+ "sitegoodsstockid": 3067777792691077
+ },
+ {
+ "sitegoodsstockid": 3067773973760901
+ },
+ {
+ "sitegoodsstockid": 3067765207436101
+ },
+ {
+ "sitegoodsstockid": 3067760818850757
+ },
+ {
+ "sitegoodsstockid": 3067759274494789
+ },
+ {
+ "sitegoodsstockid": 3067759272840005
+ },
+ {
+ "sitegoodsstockid": 3067758938492101
+ },
+ {
+ "sitegoodsstockid": 3067758937001157
+ },
+ {
+ "sitegoodsstockid": 3067758938000581
+ },
+ {
+ "sitegoodsstockid": 3067758937492677
+ },
+ {
+ "sitegoodsstockid": 3067750877989829
+ },
+ {
+ "sitegoodsstockid": 3067750878186437
+ },
+ {
+ "sitegoodsstockid": 3067750188469445
+ },
+ {
+ "sitegoodsstockid": 3067655890504581
+ },
+ {
+ "sitegoodsstockid": 3067237078174597
+ },
+ {
+ "sitegoodsstockid": 3067188787530373
+ },
+ {
+ "sitegoodsstockid": 3067182602505093
+ },
+ {
+ "sitegoodsstockid": 3067182525270917
+ },
+ {
+ "sitegoodsstockid": 3067169196329861
+ },
+ {
+ "sitegoodsstockid": 3068033580435653
+ },
+ {
+ "sitegoodsstockid": 3068033136544069
+ },
+ {
+ "sitegoodsstockid": 3068032978634885
+ },
+ {
+ "sitegoodsstockid": 3068032978126981
+ },
+ {
+ "sitegoodsstockid": 3068011017013573
+ },
+ {
+ "sitegoodsstockid": 3068009360361797
+ },
+ {
+ "sitegoodsstockid": 3068009360197957
+ },
+ {
+ "sitegoodsstockid": 3068007472859269
+ },
+ {
+ "sitegoodsstockid": 3067985548052677
+ },
+ {
+ "sitegoodsstockid": 3067982527760517
+ },
+ {
+ "sitegoodsstockid": 3067982527580293
+ },
+ {
+ "sitegoodsstockid": 3067982527400069
+ },
+ {
+ "sitegoodsstockid": 3067969529628933
+ },
+ {
+ "sitegoodsstockid": 3067960363026693
+ },
+ {
+ "sitegoodsstockid": 3067960362535173
+ },
+ {
+ "sitegoodsstockid": 3067957700249925
+ }
+ ],
+ "pages": 4,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1735,
+ "records_with_pk": 1735,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3067770378636165
+ },
+ {
+ "id": 3067252824935621
+ },
+ {
+ "id": 3067252824886469
+ },
+ {
+ "id": 3067211610753989
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 281,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 281,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 60,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:28:56.766185+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23366,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 246,
+ "ods": 246,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 3769.79,
+ "ods_sum": 3769.79,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 11546.2,
+ "ods_sum": 11546.2,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 27728.8,
+ "ods_sum": 27728.8,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 819.01,
+ "ods_sum": 819.01,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 11593.8,
+ "ods_sum": 11593.8,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18386,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2845,
+ "ods": 2845,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 328901.21,
+ "ods_sum": 328901.21,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2845,
+ "ods": 2845,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 70,
+ "ods": 70,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 18939.06,
+ "ods_sum": 18939.06,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5003,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4745,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 156,
+ "ods": 156,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 10716.0,
+ "ods_sum": 10716.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 10546.2,
+ "ods_sum": 10546.2,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11411,
+ "ods": 11411,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 172,
+ "ods": 172,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 12016.0,
+ "ods_sum": 12016.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 16977,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 455,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 281,
+ "ods": 281,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 23982.0,
+ "ods_sum": 23982.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": 0
+ },
+ "generated_at": "2026-01-26T18:29:02.395880+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 60,
+ "total_errors": 0
+ },
+ "total_missing": 60,
+ "total_errors": 0,
+ "generated_at": "2026-01-26T18:29:02.395904+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_025004.json b/etl_billiards/reports/data_integrity_window_20260127_025004.json
new file mode 100644
index 0000000..a6a5fa0
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_025004.json
@@ -0,0 +1,1309 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-26T23:44:19+08:00",
+ "end": "2026-01-27T04:44:19+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-26T23:44:19+08:00",
+ "end": "2026-01-27T04:44:19+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-26T23:44:19+08:00",
+ "end": "2026-01-27T04:44:19+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 18,
+ "missing_samples": [
+ {
+ "id": 3068517594892421
+ },
+ {
+ "id": 3068516045293893
+ },
+ {
+ "id": 3068498386438469
+ },
+ {
+ "id": 3068490926868741
+ },
+ {
+ "id": 3068488687814981
+ },
+ {
+ "id": 3068478831069509
+ },
+ {
+ "id": 3068478749411461
+ },
+ {
+ "id": 3068449874594117
+ },
+ {
+ "id": 3068439717660805
+ },
+ {
+ "id": 3068425134852421
+ },
+ {
+ "id": 3068420801906885
+ },
+ {
+ "id": 3068419354937669
+ },
+ {
+ "id": 3068405527726341
+ },
+ {
+ "id": 3068391002802501
+ },
+ {
+ "id": 3068370869831877
+ },
+ {
+ "id": 3068368265578821
+ },
+ {
+ "id": 3068365252905221
+ },
+ {
+ "id": 3068364464179397
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10017,
+ "records_with_pk": 10017,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068516486613125
+ },
+ {
+ "id": 3068516486121605
+ },
+ {
+ "id": 3068488958265669
+ },
+ {
+ "id": 3068405573077317
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11850,
+ "records_with_pk": 11850,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2475,
+ "records_with_pk": 2475,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 18,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068498975541445
+ },
+ {
+ "sitegoodsstockid": 3068496120547461
+ },
+ {
+ "sitegoodsstockid": 3068494023559365
+ },
+ {
+ "sitegoodsstockid": 3068463611513029
+ },
+ {
+ "sitegoodsstockid": 3068463611054277
+ },
+ {
+ "sitegoodsstockid": 3068449906657541
+ },
+ {
+ "sitegoodsstockid": 3068447170857285
+ },
+ {
+ "sitegoodsstockid": 3068443072497798
+ },
+ {
+ "sitegoodsstockid": 3068443072022661
+ },
+ {
+ "sitegoodsstockid": 3068443071547525
+ },
+ {
+ "sitegoodsstockid": 3068405997390085
+ },
+ {
+ "sitegoodsstockid": 3068397306628293
+ },
+ {
+ "sitegoodsstockid": 3068396797413509
+ },
+ {
+ "sitegoodsstockid": 3068396796938373
+ },
+ {
+ "sitegoodsstockid": 3068387840166021
+ },
+ {
+ "sitegoodsstockid": 3068365194758341
+ },
+ {
+ "sitegoodsstockid": 3068364728027269
+ },
+ {
+ "sitegoodsstockid": 3068363747215621
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1747,
+ "records_with_pk": 1747,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 21,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 21,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T02:49:58.098385+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18464,
+ "diff": -18463
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 19,
+ "diff": -19
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23427,
+ "diff": -61
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23427,
+ "diff": -61
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 19,
+ "diff": -19
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 600.86,
+ "diff": -600.86
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1242.0,
+ "diff": -1242.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 3514.45,
+ "diff": -3514.45
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 594.6,
+ "diff": -594.6
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 1076.99,
+ "diff": -1076.99
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18464,
+ "diff": -78
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2861,
+ "diff": -12
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332004.04,
+ "diff": -2399.5999999999767
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2861,
+ "diff": -12
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 195.07,
+ "diff": -195.07
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5016,
+ "diff": -13
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 15,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 1338.0,
+ "diff": -1338.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1242.0,
+ "diff": -1242.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 4,
+ "diff": -4
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 396.0,
+ "diff": -396.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 21,
+ "diff": -21
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 652.0,
+ "diff": -652.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18910
+ },
+ "generated_at": "2026-01-27T02:50:04.239757+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 40,
+ "total_errors": 0
+ },
+ "total_missing": 40,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T02:50:04.239796+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_034634.json b/etl_billiards/reports/data_integrity_window_20260127_034634.json
new file mode 100644
index 0000000..dfdd103
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_034634.json
@@ -0,0 +1,1322 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T00:44:19+08:00",
+ "end": "2026-01-27T05:44:19+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T00:44:19+08:00",
+ "end": "2026-01-27T05:44:19+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T00:44:19+08:00",
+ "end": "2026-01-27T05:44:19+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17,
+ "records_with_pk": 17,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3068577626589445
+ },
+ {
+ "id": 3068567310895429
+ },
+ {
+ "id": 3068565111163205
+ },
+ {
+ "id": 3068564161300741
+ },
+ {
+ "id": 3068549826037893
+ },
+ {
+ "id": 3068449874594117
+ },
+ {
+ "id": 3068439717660805
+ },
+ {
+ "id": 3068425134852421
+ },
+ {
+ "id": 3068420801906885
+ },
+ {
+ "id": 3068419354937669
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10022,
+ "records_with_pk": 10022,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068567378462917
+ },
+ {
+ "id": 3068567378446533
+ },
+ {
+ "id": 3068565155514629
+ },
+ {
+ "id": 3068564218071237
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3068567378970821
+ },
+ {
+ "id": 3068564219381957
+ },
+ {
+ "id": 3068564218923205
+ },
+ {
+ "id": 3068564218464453
+ },
+ {
+ "id": 3068550021662853
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11855,
+ "records_with_pk": 11855,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068578144979077
+ },
+ {
+ "id": 3068567373449413
+ },
+ {
+ "id": 3068565152483589
+ },
+ {
+ "id": 3068564214925509
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2479,
+ "records_with_pk": 2479,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068567374284997
+ },
+ {
+ "id": 3068567374072005
+ },
+ {
+ "id": 3068565153024261
+ },
+ {
+ "id": 3068564215498949
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068578146633861
+ },
+ {
+ "sitegoodsstockid": 3068578146486405
+ },
+ {
+ "sitegoodsstockid": 3068561912023301
+ },
+ {
+ "sitegoodsstockid": 3068549681596741
+ },
+ {
+ "sitegoodsstockid": 3068549681105221
+ },
+ {
+ "sitegoodsstockid": 3068463611513029
+ },
+ {
+ "sitegoodsstockid": 3068463611054277
+ },
+ {
+ "sitegoodsstockid": 3068449906657541
+ },
+ {
+ "sitegoodsstockid": 3068447170857285
+ },
+ {
+ "sitegoodsstockid": 3068443072497798
+ },
+ {
+ "sitegoodsstockid": 3068443072022661
+ },
+ {
+ "sitegoodsstockid": 3068443071547525
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1752,
+ "records_with_pk": 1752,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3068567379904709
+ },
+ {
+ "id": 3068567379970245
+ },
+ {
+ "id": 3068565156202757
+ },
+ {
+ "id": 3068564220086469
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 17,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 17,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 43,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T03:46:28.100178+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18465,
+ "diff": -18464
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 12,
+ "diff": -12
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23434,
+ "diff": -68
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23434,
+ "diff": -68
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 12,
+ "diff": -12
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 382.98,
+ "diff": -382.98
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 828.0,
+ "diff": -828.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 2384.57,
+ "diff": -2384.57
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 594.6,
+ "diff": -594.6
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 578.99,
+ "diff": -578.99
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18465,
+ "diff": -79
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2862,
+ "diff": -13
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332087.01,
+ "diff": -2482.570000000007
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2862,
+ "diff": -13
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1773.59,
+ "diff": -1773.59
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5019,
+ "diff": -16
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4760,
+ "diff": -15
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 924.0,
+ "diff": -924.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 828.0,
+ "diff": -828.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 13,
+ "diff": -13
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 324.0,
+ "diff": -324.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18901
+ },
+ "generated_at": "2026-01-27T03:46:34.507148+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 43,
+ "total_errors": 0
+ },
+ "total_missing": 43,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T03:46:34.507172+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_044633.json b/etl_billiards/reports/data_integrity_window_20260127_044633.json
new file mode 100644
index 0000000..13bf6f5
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_044633.json
@@ -0,0 +1,1232 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T01:44:19+08:00",
+ "end": "2026-01-27T06:44:19+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T01:44:19+08:00",
+ "end": "2026-01-27T06:44:19+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T01:44:19+08:00",
+ "end": "2026-01-27T06:44:19+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 13,
+ "records_with_pk": 13,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068598449785093
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10023,
+ "records_with_pk": 10023,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068598529034565
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068598530050373
+ },
+ {
+ "id": 3068598529591621
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11857,
+ "records_with_pk": 11857,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068598524643653
+ },
+ {
+ "id": 3068597555480709
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2482,
+ "records_with_pk": 2482,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3068632370661253
+ },
+ {
+ "id": 3068598525233477
+ },
+ {
+ "id": 3068597557135493
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068597553416325
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 11,
+ "records_with_pk": 11,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068636706687301
+ },
+ {
+ "sitegoodsstockid": 3068631858153669
+ },
+ {
+ "sitegoodsstockid": 3068631857645765
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1752,
+ "records_with_pk": 1752,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 14,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 14,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T04:46:27.497118+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18469,
+ "diff": -18468
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 12,
+ "diff": -12
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23439,
+ "diff": -73
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23439,
+ "diff": -73
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 12,
+ "diff": -12
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 513.39,
+ "diff": -513.39
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 348.0,
+ "diff": -348.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 2105.41,
+ "diff": -2105.41
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 594.6,
+ "diff": -594.6
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 649.42,
+ "diff": -649.42
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18469,
+ "diff": -83
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 8,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 2245.45,
+ "diff": -2245.45
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5024,
+ "diff": -21
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4764,
+ "diff": -19
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4764,
+ "diff": -19
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 348.0,
+ "diff": -348.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 348.0,
+ "diff": -348.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 456,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 12,
+ "diff": -12
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 313.0,
+ "diff": -313.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18938
+ },
+ "generated_at": "2026-01-27T04:46:33.029842+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 13,
+ "total_errors": 0
+ },
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T04:46:33.029862+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_054632.json b/etl_billiards/reports/data_integrity_window_20260127_054632.json
new file mode 100644
index 0000000..b40c631
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_054632.json
@@ -0,0 +1,1206 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T02:44:19+08:00",
+ "end": "2026-01-27T07:44:19+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T02:44:19+08:00",
+ "end": "2026-01-27T07:44:19+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T02:44:19+08:00",
+ "end": "2026-01-27T07:44:19+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068658449336453
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10024,
+ "records_with_pk": 10024,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068658720344389
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068658720835909
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11858,
+ "records_with_pk": 11858,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068658716870981
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2483,
+ "records_with_pk": 2483,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068658717411653
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1752,
+ "records_with_pk": 1752,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 8,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 8,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T05:46:26.660167+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18470,
+ "diff": -18469
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 6,
+ "diff": -6
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23440,
+ "diff": -74
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23440,
+ "diff": -74
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 6,
+ "diff": -6
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 213.38,
+ "diff": -213.38
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1045.17,
+ "diff": -1045.17
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 831.79,
+ "diff": -831.79
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18470,
+ "diff": -84
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 7,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1865.09,
+ "diff": -1865.09
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5026,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4767,
+ "diff": -22
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4767,
+ "diff": -22
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 7,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 3295.0,
+ "diff": -3295.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18931
+ },
+ "generated_at": "2026-01-27T05:46:32.261928+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 5,
+ "total_errors": 0
+ },
+ "total_missing": 5,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T05:46:32.261995+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_064633.json b/etl_billiards/reports/data_integrity_window_20260127_064633.json
new file mode 100644
index 0000000..eb4106d
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_064633.json
@@ -0,0 +1,1213 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T03:44:19+08:00",
+ "end": "2026-01-27T08:44:19+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T03:44:19+08:00",
+ "end": "2026-01-27T08:44:19+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T03:44:19+08:00",
+ "end": "2026-01-27T08:44:19+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068721501554821
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10025,
+ "records_with_pk": 10025,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068721549396165
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068721549789381
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11859,
+ "records_with_pk": 11859,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068721545955525
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2485,
+ "records_with_pk": 2485,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068721546709189
+ },
+ {
+ "id": 3068721546512581
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068730254100741
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1752,
+ "records_with_pk": 1752,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 4,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 7,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T06:46:27.649849+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18471,
+ "diff": -18470
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23441,
+ "diff": -75
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23441,
+ "diff": -75
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 749.43,
+ "diff": -749.43
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 749.43,
+ "diff": -749.43
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18471,
+ "diff": -85
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1597.51,
+ "diff": -1597.51
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5027,
+ "diff": -24
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4768,
+ "diff": -23
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4768,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 3000.0,
+ "diff": -3000.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18922
+ },
+ "generated_at": "2026-01-27T06:46:33.941851+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 7,
+ "total_errors": 0
+ },
+ "total_missing": 7,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T06:46:33.941872+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_074634.json b/etl_billiards/reports/data_integrity_window_20260127_074634.json
new file mode 100644
index 0000000..dad738a
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_074634.json
@@ -0,0 +1,1198 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T04:44:20+08:00",
+ "end": "2026-01-27T09:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T04:44:20+08:00",
+ "end": "2026-01-27T09:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T04:44:20+08:00",
+ "end": "2026-01-27T09:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068814932084997
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10026,
+ "records_with_pk": 10026,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068815491205445
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11860,
+ "records_with_pk": 11860,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3068815488616773
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2485,
+ "records_with_pk": 2485,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8222,
+ "records_with_pk": 8222,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1752,
+ "records_with_pk": 1752,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 3,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 3,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T07:46:28.145858+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18472,
+ "diff": -18471
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23442,
+ "diff": -76
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23442,
+ "diff": -76
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 240.99,
+ "diff": -240.99
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 240.99,
+ "diff": -240.99
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18472,
+ "diff": -86
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 520.48,
+ "diff": -520.48
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18929
+ },
+ "generated_at": "2026-01-27T07:46:34.370116+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 3,
+ "total_errors": 0
+ },
+ "total_missing": 3,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T07:46:34.370139+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_084637.json b/etl_billiards/reports/data_integrity_window_20260127_084637.json
new file mode 100644
index 0000000..3caacac
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_084637.json
@@ -0,0 +1,1186 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T05:44:20+08:00",
+ "end": "2026-01-27T10:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T05:44:20+08:00",
+ "end": "2026-01-27T10:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T05:44:20+08:00",
+ "end": "2026-01-27T10:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11789,
+ "records_with_pk": 11789,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8186,
+ "records_with_pk": 8186,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 2,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 2,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T08:46:31.063797+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 448.01,
+ "diff": -448.01
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 448.01,
+ "diff": -448.01
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 316.2,
+ "diff": -316.2
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 289.0,
+ "diff": -289.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18932
+ },
+ "generated_at": "2026-01-27T08:46:37.552132+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 0,
+ "total_errors": 0
+ },
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T08:46:37.552154+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_094626.json b/etl_billiards/reports/data_integrity_window_20260127_094626.json
new file mode 100644
index 0000000..ac966ba
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_094626.json
@@ -0,0 +1,1186 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T06:44:20+08:00",
+ "end": "2026-01-27T11:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T06:44:20+08:00",
+ "end": "2026-01-27T11:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T06:44:20+08:00",
+ "end": "2026-01-27T11:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11789,
+ "records_with_pk": 11789,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2466,
+ "records_with_pk": 2466,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8186,
+ "records_with_pk": 8186,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 1,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T09:46:20.632253+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 278.07,
+ "diff": -278.07
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 278.07,
+ "diff": -278.07
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 289.0,
+ "diff": -289.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18928
+ },
+ "generated_at": "2026-01-27T09:46:26.587182+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 0,
+ "total_errors": 0
+ },
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T09:46:26.587210+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_104627.json b/etl_billiards/reports/data_integrity_window_20260127_104627.json
new file mode 100644
index 0000000..aa5f7f2
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_104627.json
@@ -0,0 +1,1214 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T07:44:20+08:00",
+ "end": "2026-01-27T12:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T07:44:20+08:00",
+ "end": "2026-01-27T12:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T07:44:20+08:00",
+ "end": "2026-01-27T12:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068960095340677
+ },
+ {
+ "id": 3068958193125637
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11791,
+ "records_with_pk": 11791,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068960138873157
+ },
+ {
+ "id": 3068958260365509
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3068960139462981
+ },
+ {
+ "id": 3068958260955333
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8186,
+ "records_with_pk": 8186,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3068960140773701
+ },
+ {
+ "sitegoodsstockid": 3068958262266053
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 2,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 2,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 8,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T10:46:21.863125+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23443,
+ "diff": -77
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4770,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18925
+ },
+ "generated_at": "2026-01-27T10:46:27.595443+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 8,
+ "total_errors": 0
+ },
+ "total_missing": 8,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T10:46:27.595465+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_114628.json b/etl_billiards/reports/data_integrity_window_20260127_114628.json
new file mode 100644
index 0000000..4735829
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_114628.json
@@ -0,0 +1,1186 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T08:44:20+08:00",
+ "end": "2026-01-27T13:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T08:44:20+08:00",
+ "end": "2026-01-27T13:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T08:44:20+08:00",
+ "end": "2026-01-27T13:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11791,
+ "records_with_pk": 11791,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2468,
+ "records_with_pk": 2468,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8186,
+ "records_with_pk": 8186,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 2,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 2,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T11:46:23.240215+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23445,
+ "diff": -79
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23445,
+ "diff": -79
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4772,
+ "diff": -27
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4772,
+ "diff": -27
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18935
+ },
+ "generated_at": "2026-01-27T11:46:28.334055+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 0,
+ "total_errors": 0
+ },
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T11:46:28.334079+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_124632.json b/etl_billiards/reports/data_integrity_window_20260127_124632.json
new file mode 100644
index 0000000..ca97909
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_124632.json
@@ -0,0 +1,1217 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T09:44:20+08:00",
+ "end": "2026-01-27T14:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T09:44:20+08:00",
+ "end": "2026-01-27T14:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T09:44:20+08:00",
+ "end": "2026-01-27T14:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069083611875653
+ },
+ {
+ "id": 3069071521466693
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11793,
+ "records_with_pk": 11793,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069083636582661
+ },
+ {
+ "id": 3069071572748421
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17031,
+ "records_with_pk": 17031,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2470,
+ "records_with_pk": 2470,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069083637123333
+ },
+ {
+ "id": 3069071573436549
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8186,
+ "records_with_pk": 8186,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069083638515973
+ },
+ {
+ "sitegoodsstockid": 3069071575058565
+ },
+ {
+ "sitegoodsstockid": 3069071574878341
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 4,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 9,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T12:46:26.353424+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23445,
+ "diff": -79
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23445,
+ "diff": -79
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4772,
+ "diff": -27
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4772,
+ "diff": -27
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18935
+ },
+ "generated_at": "2026-01-27T12:46:32.092937+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 9,
+ "total_errors": 0
+ },
+ "total_missing": 9,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T12:46:32.092963+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_134628.json b/etl_billiards/reports/data_integrity_window_20260127_134628.json
new file mode 100644
index 0000000..3446754
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_134628.json
@@ -0,0 +1,1190 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T10:44:20+08:00",
+ "end": "2026-01-27T15:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T10:44:20+08:00",
+ "end": "2026-01-27T15:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T10:44:20+08:00",
+ "end": "2026-01-27T15:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9965,
+ "records_with_pk": 9965,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11793,
+ "records_with_pk": 11793,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17032,
+ "records_with_pk": 17032,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069132833818821
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2470,
+ "records_with_pk": 2470,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3400,
+ "records_with_pk": 3400,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetSiteTableUseDetails"
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsStockReport"
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/GoodsStockManage/QueryGoodsOutboundReceipt"
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/Table/GetSiteTables"
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 3,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 3,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 4,
+ "generated_at": "2026-01-27T13:46:21.588530+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23447,
+ "diff": -81
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23447,
+ "diff": -81
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17031,
+ "diff": -54
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18943
+ },
+ "generated_at": "2026-01-27T13:46:28.584475+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 1,
+ "total_errors": 4
+ },
+ "total_missing": 1,
+ "total_errors": 4,
+ "generated_at": "2026-01-27T13:46:28.584495+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_144641.json b/etl_billiards/reports/data_integrity_window_20260127_144641.json
new file mode 100644
index 0000000..aaadc4b
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_144641.json
@@ -0,0 +1,1231 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T11:44:20+08:00",
+ "end": "2026-01-27T16:44:20+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T11:44:20+08:00",
+ "end": "2026-01-27T16:44:20+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T11:44:20+08:00",
+ "end": "2026-01-27T16:44:20+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069194573040709
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9966,
+ "records_with_pk": 9966,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069194594815173
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11795,
+ "records_with_pk": 11795,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069194592554181
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17039,
+ "records_with_pk": 17039,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3069222277008453
+ },
+ {
+ "id": 3069220929784901
+ },
+ {
+ "id": 3069202794122309
+ },
+ {
+ "id": 3069200543911109
+ },
+ {
+ "id": 3069200431451461
+ },
+ {
+ "id": 3069194502802501
+ },
+ {
+ "id": 3069176595680325
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2470,
+ "records_with_pk": 2470,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8187,
+ "records_with_pk": 8187,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069194595355845
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 8,
+ "records_with_pk": 8,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069181470870597
+ },
+ {
+ "sitegoodsstockid": 3069181470329925
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1740,
+ "records_with_pk": 1740,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 4,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 4,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T14:46:34.959226+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18473,
+ "diff": -18472
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23447,
+ "diff": -81
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23447,
+ "diff": -81
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18473,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11489,
+ "diff": -62
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 48.0,
+ "diff": -48.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17032,
+ "diff": -55
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18946
+ },
+ "generated_at": "2026-01-27T14:46:41.674562+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 13,
+ "total_errors": 0
+ },
+ "total_missing": 13,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T14:46:41.674607+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_154658.json b/etl_billiards/reports/data_integrity_window_20260127_154658.json
new file mode 100644
index 0000000..87cc37c
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_154658.json
@@ -0,0 +1,1250 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T12:44:21+08:00",
+ "end": "2026-01-27T17:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T12:44:21+08:00",
+ "end": "2026-01-27T17:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T12:44:21+08:00",
+ "end": "2026-01-27T17:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069269358021957
+ },
+ {
+ "id": 3069269302348997
+ },
+ {
+ "id": 3069238704622661
+ },
+ {
+ "id": 3069238635908229
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9970,
+ "records_with_pk": 9970,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069269377436805
+ },
+ {
+ "id": 3069269322747205
+ },
+ {
+ "id": 3069238720564421
+ },
+ {
+ "id": 3069238655323205
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11799,
+ "records_with_pk": 11799,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069269374717061
+ },
+ {
+ "id": 3069269320387909
+ },
+ {
+ "id": 3069238718336197
+ },
+ {
+ "id": 3069238652718149
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17041,
+ "records_with_pk": 17041,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069270640872645
+ },
+ {
+ "id": 3069252816292933
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2470,
+ "records_with_pk": 2470,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8190,
+ "records_with_pk": 8190,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3069269380353157
+ },
+ {
+ "id": 3069269323533637
+ },
+ {
+ "id": 3069238721170629
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069279112006725
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069238655994949
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 6,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 6,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 19,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T15:46:48.534957+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18474,
+ "diff": -18473
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23448,
+ "diff": -82
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23448,
+ "diff": -82
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 48.0,
+ "diff": -48.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 48.0,
+ "diff": -48.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18474,
+ "diff": -88
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332217.42,
+ "diff": -2612.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2866,
+ "diff": -17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 48.0,
+ "diff": -48.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 48.0,
+ "diff": -48.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11490,
+ "diff": -63
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 8,
+ "diff": -8
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 452.0,
+ "diff": -452.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17039,
+ "diff": -62
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -18967
+ },
+ "generated_at": "2026-01-27T15:46:58.660937+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 19,
+ "total_errors": 0
+ },
+ "total_missing": 19,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T15:46:58.660969+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_164657.json b/etl_billiards/reports/data_integrity_window_20260127_164657.json
new file mode 100644
index 0000000..625ab54
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_164657.json
@@ -0,0 +1,1279 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T13:44:21+08:00",
+ "end": "2026-01-27T18:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T13:44:21+08:00",
+ "end": "2026-01-27T18:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T13:44:21+08:00",
+ "end": "2026-01-27T18:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10,
+ "records_with_pk": 10,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069343017372741
+ },
+ {
+ "id": 3069335073688773
+ },
+ {
+ "id": 3069335023438981
+ },
+ {
+ "id": 3069312330943557
+ },
+ {
+ "id": 3069310506569029
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9975,
+ "records_with_pk": 9975,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069343035657541
+ },
+ {
+ "id": 3069335093316741
+ },
+ {
+ "id": 3069335041346629
+ },
+ {
+ "id": 3069312347294917
+ },
+ {
+ "id": 3069310527376517
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11804,
+ "records_with_pk": 11804,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069343033429317
+ },
+ {
+ "id": 3069335090449541
+ },
+ {
+ "id": 3069335039102021
+ },
+ {
+ "id": 3069312345099461
+ },
+ {
+ "id": 3069310524722309
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17043,
+ "records_with_pk": 17043,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069312743214277
+ },
+ {
+ "id": 3069311491607685
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2470,
+ "records_with_pk": 2470,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8196,
+ "records_with_pk": 8196,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069343036280133
+ },
+ {
+ "id": 3069335093922949
+ },
+ {
+ "id": 3069335041903685
+ },
+ {
+ "id": 3069335041903686
+ },
+ {
+ "id": 3069312347966661
+ },
+ {
+ "id": 3069310527933573
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069346477395077
+ },
+ {
+ "sitegoodsstockid": 3069339653590213
+ },
+ {
+ "sitegoodsstockid": 3069330050829445
+ },
+ {
+ "sitegoodsstockid": 3069301909818565
+ },
+ {
+ "sitegoodsstockid": 3069299023432901
+ },
+ {
+ "sitegoodsstockid": 3069298646535301
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1741,
+ "records_with_pk": 1741,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 11,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 11,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 29,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T16:46:50.776877+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18478,
+ "diff": -18477
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 5,
+ "diff": -5
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23452,
+ "diff": -86
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23452,
+ "diff": -86
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 5,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 192.0,
+ "diff": -192.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 240.0,
+ "diff": -240.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18478,
+ "diff": -92
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2867,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332241.42,
+ "diff": -2636.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2867,
+ "diff": -18
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 4,
+ "diff": -4
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 192.0,
+ "diff": -192.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 192.0,
+ "diff": -192.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11493,
+ "diff": -66
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 500.0,
+ "diff": -500.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17041,
+ "diff": -64
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 6,
+ "diff": -6
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19006
+ },
+ "generated_at": "2026-01-27T16:46:57.948203+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 29,
+ "total_errors": 0
+ },
+ "total_missing": 29,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T16:46:57.948234+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_174656.json b/etl_billiards/reports/data_integrity_window_20260127_174656.json
new file mode 100644
index 0000000..3bdb047
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_174656.json
@@ -0,0 +1,1311 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T14:44:21+08:00",
+ "end": "2026-01-27T19:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T14:44:21+08:00",
+ "end": "2026-01-27T19:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T14:44:21+08:00",
+ "end": "2026-01-27T19:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069406529948741
+ },
+ {
+ "id": 3069403912490117
+ },
+ {
+ "id": 3069403467074629
+ },
+ {
+ "id": 3069387495476421
+ },
+ {
+ "id": 3069376910609605
+ },
+ {
+ "id": 3069363119951174
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9980,
+ "records_with_pk": 9980,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069406549855365
+ },
+ {
+ "id": 3069403487866181
+ },
+ {
+ "id": 3069403487898949
+ },
+ {
+ "id": 3069387515202885
+ },
+ {
+ "id": 3069363272846469
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11810,
+ "records_with_pk": 11810,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069406547479685
+ },
+ {
+ "id": 3069403964263621
+ },
+ {
+ "id": 3069403484654917
+ },
+ {
+ "id": 3069387513154885
+ },
+ {
+ "id": 3069376933203077
+ },
+ {
+ "id": 3069363270798469
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17047,
+ "records_with_pk": 17047,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069408707792069
+ },
+ {
+ "id": 3069387415211205
+ },
+ {
+ "id": 3069387257236613
+ },
+ {
+ "id": 3069360863759429
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2472,
+ "records_with_pk": 2472,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069403964837061
+ },
+ {
+ "id": 3069376933776517
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8197,
+ "records_with_pk": 8197,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069387515727173
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 21,
+ "records_with_pk": 21,
+ "missing": 14,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069403966475461
+ },
+ {
+ "sitegoodsstockid": 3069403966311621
+ },
+ {
+ "sitegoodsstockid": 3069403966147781
+ },
+ {
+ "sitegoodsstockid": 3069403365854533
+ },
+ {
+ "sitegoodsstockid": 3069403295993029
+ },
+ {
+ "sitegoodsstockid": 3069403235781701
+ },
+ {
+ "sitegoodsstockid": 3069401598643333
+ },
+ {
+ "sitegoodsstockid": 3069401146821957
+ },
+ {
+ "sitegoodsstockid": 3069401146330437
+ },
+ {
+ "sitegoodsstockid": 3069399619750981
+ },
+ {
+ "sitegoodsstockid": 3069396427672773
+ },
+ {
+ "sitegoodsstockid": 3069383742213317
+ },
+ {
+ "sitegoodsstockid": 3069376935103621
+ },
+ {
+ "sitegoodsstockid": 3069375456906565
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1742,
+ "records_with_pk": 1742,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069403488718149
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 15,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 15,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 39,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T17:46:49.943286+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18483,
+ "diff": -18482
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23457,
+ "diff": -91
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23457,
+ "diff": -91
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 500.0,
+ "diff": -500.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 548.0,
+ "diff": -548.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 24.0,
+ "diff": -24.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18483,
+ "diff": -97
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2867,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332241.42,
+ "diff": -2636.9799999999814
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2867,
+ "diff": -18
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4774,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 500.0,
+ "diff": -500.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 500.0,
+ "diff": -500.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11499,
+ "diff": -72
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 4,
+ "diff": -4
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 288.0,
+ "diff": -288.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17043,
+ "diff": -66
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19045
+ },
+ "generated_at": "2026-01-27T17:46:56.000670+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 39,
+ "total_errors": 0
+ },
+ "total_missing": 39,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T17:46:56.000746+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_184644.json b/etl_billiards/reports/data_integrity_window_20260127_184644.json
new file mode 100644
index 0000000..7831132
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_184644.json
@@ -0,0 +1,1306 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T15:44:21+08:00",
+ "end": "2026-01-27T20:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T15:44:21+08:00",
+ "end": "2026-01-27T20:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T15:44:21+08:00",
+ "end": "2026-01-27T20:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 15,
+ "records_with_pk": 15,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069449296252037
+ },
+ {
+ "id": 3069444110224581
+ },
+ {
+ "id": 3069420764007493
+ },
+ {
+ "id": 3069420571200645
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9983,
+ "records_with_pk": 9983,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3069449503050949
+ },
+ {
+ "id": 3069420963990725
+ },
+ {
+ "id": 3069420600904773
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2,
+ "records_with_pk": 2,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069449503476933
+ },
+ {
+ "id": 3069420964465861
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11814,
+ "records_with_pk": 11814,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069449499610309
+ },
+ {
+ "id": 3069444129590597
+ },
+ {
+ "id": 3069420961516741
+ },
+ {
+ "id": 3069420598594629
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17053,
+ "records_with_pk": 17053,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069465494146373
+ },
+ {
+ "id": 3069462511766597
+ },
+ {
+ "id": 3069461015661894
+ },
+ {
+ "id": 3069461015661893
+ },
+ {
+ "id": 3069452774296901
+ },
+ {
+ "id": 3069429108378949
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2474,
+ "records_with_pk": 2474,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069449500232901
+ },
+ {
+ "id": 3069444130180421
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8199,
+ "records_with_pk": 8199,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069468823555397
+ },
+ {
+ "id": 3069420601510981
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsid": 3069455725923269
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28,
+ "records_with_pk": 28,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069459845975109
+ },
+ {
+ "sitegoodsstockid": 3069459845450821
+ },
+ {
+ "sitegoodsstockid": 3069456207727493
+ },
+ {
+ "sitegoodsstockid": 3069456207661957
+ },
+ {
+ "sitegoodsstockid": 3069453684165765
+ },
+ {
+ "sitegoodsstockid": 3069452660247685
+ },
+ {
+ "sitegoodsstockid": 3069444131867973
+ },
+ {
+ "sitegoodsstockid": 3069444131687749
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069455725923269
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1744,
+ "records_with_pk": 1744,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069449504246981
+ },
+ {
+ "id": 3069420965416133
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069455434189829
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 16,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 16,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 36,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T18:46:39.712646+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18488,
+ "diff": -18487
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 171,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 170,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23463,
+ "diff": -97
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23463,
+ "diff": -97
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 492.97,
+ "diff": -492.97
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 416.83,
+ "diff": -416.83
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1588.16,
+ "diff": -1588.16
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 104.34,
+ "diff": -104.34
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 574.02,
+ "diff": -574.02
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18488,
+ "diff": -102
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2868,
+ "diff": -19
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332734.39,
+ "diff": -3129.9500000000116
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2868,
+ "diff": -19
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5028,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4776,
+ "diff": -31
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4776,
+ "diff": -31
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 7,
+ "diff": -7
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 452.0,
+ "diff": -452.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 416.83,
+ "diff": -416.83
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11500,
+ "diff": -73
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 6,
+ "diff": -6
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 624.0,
+ "diff": -624.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17047,
+ "diff": -70
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 11,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 675.0,
+ "diff": -675.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19082
+ },
+ "generated_at": "2026-01-27T18:46:44.733274+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 36,
+ "total_errors": 0
+ },
+ "total_missing": 36,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T18:46:44.733344+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_194657.json b/etl_billiards/reports/data_integrity_window_20260127_194657.json
new file mode 100644
index 0000000..708c985
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_194657.json
@@ -0,0 +1,1291 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T16:44:21+08:00",
+ "end": "2026-01-27T21:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T16:44:21+08:00",
+ "end": "2026-01-27T21:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T16:44:21+08:00",
+ "end": "2026-01-27T21:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16,
+ "records_with_pk": 16,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069521175661893
+ },
+ {
+ "id": 3069513038499013
+ },
+ {
+ "id": 3069508165897349
+ },
+ {
+ "id": 3069503159029061
+ },
+ {
+ "id": 3069498507463813
+ },
+ {
+ "id": 3069468806810757
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9990,
+ "records_with_pk": 9990,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3069521208397125
+ },
+ {
+ "id": 3069513063763269
+ },
+ {
+ "id": 3069508184149061
+ },
+ {
+ "id": 3069503187389573
+ },
+ {
+ "id": 3069503187373189
+ },
+ {
+ "id": 3069498637159557
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069498637651077
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11820,
+ "records_with_pk": 11820,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069521206054213
+ },
+ {
+ "id": 3069513061485893
+ },
+ {
+ "id": 3069508181675077
+ },
+ {
+ "id": 3069503184080005
+ },
+ {
+ "id": 3069498633456773
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17058,
+ "records_with_pk": 17058,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069527606037829
+ },
+ {
+ "id": 3069503737662533
+ },
+ {
+ "id": 3069501231451461
+ },
+ {
+ "id": 3069500594507077
+ },
+ {
+ "id": 3069487747320901
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2476,
+ "records_with_pk": 2476,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069498634259589
+ },
+ {
+ "id": 3069498634046597
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8202,
+ "records_with_pk": 8202,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3069513064336709
+ },
+ {
+ "id": 3069508184722501
+ },
+ {
+ "id": 3069508184722502
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 25,
+ "records_with_pk": 25,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069473975520453
+ },
+ {
+ "sitegoodsstockid": 3069473974439109
+ },
+ {
+ "sitegoodsstockid": 3069473975028933
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1745,
+ "records_with_pk": 1745,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069503188339845
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 16,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 16,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 32,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T19:46:51.926185+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18492,
+ "diff": -18491
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 172,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23467,
+ "diff": -101
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23467,
+ "diff": -101
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 9,
+ "diff": -9
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 625.88,
+ "diff": -625.88
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 197.58,
+ "diff": -197.58
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1634.74,
+ "diff": -1634.74
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 104.34,
+ "diff": -104.34
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 706.94,
+ "diff": -706.94
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18492,
+ "diff": -106
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2870,
+ "diff": -21
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332867.3,
+ "diff": -3262.859999999986
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2870,
+ "diff": -21
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 2,
+ "diff": -2
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 236.39,
+ "diff": -236.39
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5030,
+ "diff": -27
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4778,
+ "diff": -33
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4778,
+ "diff": -33
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 240.0,
+ "diff": -240.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 197.58,
+ "diff": -197.58
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11502,
+ "diff": -75
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 864.0,
+ "diff": -864.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17053,
+ "diff": -76
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 11,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 997.0,
+ "diff": -997.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19120
+ },
+ "generated_at": "2026-01-27T19:46:57.190523+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 32,
+ "total_errors": 0
+ },
+ "total_missing": 32,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T19:46:57.190544+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_204701.json b/etl_billiards/reports/data_integrity_window_20260127_204701.json
new file mode 100644
index 0000000..418aa8e
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_204701.json
@@ -0,0 +1,1426 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T17:44:21+08:00",
+ "end": "2026-01-27T22:44:21+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T17:44:21+08:00",
+ "end": "2026-01-27T22:44:21+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T17:44:21+08:00",
+ "end": "2026-01-27T22:44:21+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 19,
+ "records_with_pk": 19,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3069583577599109
+ },
+ {
+ "id": 3069579197877317
+ },
+ {
+ "id": 3069563572669637
+ },
+ {
+ "id": 3069550199000197
+ },
+ {
+ "id": 3069547441966277
+ },
+ {
+ "id": 3069547312843845
+ },
+ {
+ "id": 3069540311141509
+ },
+ {
+ "id": 3069537446579269
+ },
+ {
+ "id": 3069537011535173
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10002,
+ "records_with_pk": 10002,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3069583600553285
+ },
+ {
+ "id": 3069579217538373
+ },
+ {
+ "id": 3069563588234437
+ },
+ {
+ "id": 3069550227917893
+ },
+ {
+ "id": 3069547463675205
+ },
+ {
+ "id": 3069547332472005
+ },
+ {
+ "id": 3069540354575557
+ },
+ {
+ "id": 3069540354591941
+ },
+ {
+ "id": 3069537546620229
+ },
+ {
+ "id": 3069537546636613
+ },
+ {
+ "id": 3069537144048965
+ },
+ {
+ "id": 3069537144065349
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 5,
+ "records_with_pk": 5,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069537547046213
+ },
+ {
+ "id": 3069537144540485
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11829,
+ "records_with_pk": 11829,
+ "missing": 9,
+ "missing_samples": [
+ {
+ "id": 3069583598325061
+ },
+ {
+ "id": 3069579212688709
+ },
+ {
+ "id": 3069563585940677
+ },
+ {
+ "id": 3069550225607749
+ },
+ {
+ "id": 3069547461250373
+ },
+ {
+ "id": 3069547330227397
+ },
+ {
+ "id": 3069540351478981
+ },
+ {
+ "id": 3069537543179589
+ },
+ {
+ "id": 3069537139985733
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17070,
+ "records_with_pk": 17070,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3069585874013381
+ },
+ {
+ "id": 3069583920090181
+ },
+ {
+ "id": 3069583419722949
+ },
+ {
+ "id": 3069581359893701
+ },
+ {
+ "id": 3069566724508741
+ },
+ {
+ "id": 3069560753179973
+ },
+ {
+ "id": 3069551635991621
+ },
+ {
+ "id": 3069550428753221
+ },
+ {
+ "id": 3069549636471877
+ },
+ {
+ "id": 3069539710749765
+ },
+ {
+ "id": 3069539173125253
+ },
+ {
+ "id": 3069539042315461
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2478,
+ "records_with_pk": 2478,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069537543720261
+ },
+ {
+ "id": 3069537140559173
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8211,
+ "records_with_pk": 8211,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3069583604059461
+ },
+ {
+ "id": 3069579218128197
+ },
+ {
+ "id": 3069579218111813
+ },
+ {
+ "id": 3069563588791493
+ },
+ {
+ "id": 3069547464248645
+ },
+ {
+ "id": 3069547333143749
+ },
+ {
+ "id": 3069540355280069
+ },
+ {
+ "id": 3069540355280070
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 33,
+ "records_with_pk": 33,
+ "missing": 22,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069575024954565
+ },
+ {
+ "sitegoodsstockid": 3069567826464069
+ },
+ {
+ "sitegoodsstockid": 3069567367531397
+ },
+ {
+ "sitegoodsstockid": 3069567367613317
+ },
+ {
+ "sitegoodsstockid": 3069560107027781
+ },
+ {
+ "sitegoodsstockid": 3069545186774341
+ },
+ {
+ "sitegoodsstockid": 3069532651129925
+ },
+ {
+ "sitegoodsstockid": 3069532653292613
+ },
+ {
+ "sitegoodsstockid": 3069532655324229
+ },
+ {
+ "sitegoodsstockid": 3069532657945669
+ },
+ {
+ "sitegoodsstockid": 3069532650622021
+ },
+ {
+ "sitegoodsstockid": 3069532652784709
+ },
+ {
+ "sitegoodsstockid": 3069532654816325
+ },
+ {
+ "sitegoodsstockid": 3069532651621445
+ },
+ {
+ "sitegoodsstockid": 3069532654308421
+ },
+ {
+ "sitegoodsstockid": 3069532652293189
+ },
+ {
+ "sitegoodsstockid": 3069532653800517
+ },
+ {
+ "sitegoodsstockid": 3069532655832133
+ },
+ {
+ "sitegoodsstockid": 3069532656356421
+ },
+ {
+ "sitegoodsstockid": 3069532656880709
+ },
+ {
+ "sitegoodsstockid": 3069532657404997
+ },
+ {
+ "sitegoodsstockid": 3069532658453573
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1746,
+ "records_with_pk": 1746,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3069550228720709
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 20,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 20,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 77,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T20:46:54.894452+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18498,
+ "diff": -18497
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 172,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23473,
+ "diff": -107
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23473,
+ "diff": -107
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 133.36,
+ "diff": -133.36
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 280.75,
+ "diff": -280.75
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1249.91,
+ "diff": -1249.91
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 390.03,
+ "diff": -390.03
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 445.77,
+ "diff": -445.77
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18498,
+ "diff": -112
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2871,
+ "diff": -22
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332867.75,
+ "diff": -3263.3099999999977
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2871,
+ "diff": -22
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 331.61,
+ "diff": -331.61
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5031,
+ "diff": -28
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4780,
+ "diff": -35
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4780,
+ "diff": -35
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 5,
+ "diff": -5
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 288.0,
+ "diff": -288.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 280.75,
+ "diff": -280.75
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11505,
+ "diff": -78
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 11,
+ "diff": -11
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 808.0,
+ "diff": -808.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17058,
+ "diff": -81
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 10,
+ "diff": -10
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 622.0,
+ "diff": -622.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19164
+ },
+ "generated_at": "2026-01-27T20:47:01.198570+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 77,
+ "total_errors": 0
+ },
+ "total_missing": 77,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T20:47:01.198606+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_214717.json b/etl_billiards/reports/data_integrity_window_20260127_214717.json
new file mode 100644
index 0000000..3fce826
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_214717.json
@@ -0,0 +1,1494 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T18:44:22+08:00",
+ "end": "2026-01-27T23:44:22+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T18:44:22+08:00",
+ "end": "2026-01-27T23:44:22+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T18:44:22+08:00",
+ "end": "2026-01-27T23:44:22+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 5,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 27,
+ "records_with_pk": 27,
+ "missing": 12,
+ "missing_samples": [
+ {
+ "id": 3069634632125573
+ },
+ {
+ "id": 3069632780668229
+ },
+ {
+ "id": 3069632217517253
+ },
+ {
+ "id": 3069625367481477
+ },
+ {
+ "id": 3069616408988741
+ },
+ {
+ "id": 3069615734115525
+ },
+ {
+ "id": 3069610893266053
+ },
+ {
+ "id": 3069610827664517
+ },
+ {
+ "id": 3069609511652549
+ },
+ {
+ "id": 3069603722857797
+ },
+ {
+ "id": 3069589365394501
+ },
+ {
+ "id": 3069588118326405
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10013,
+ "records_with_pk": 10013,
+ "missing": 10,
+ "missing_samples": [
+ {
+ "id": 3069634688535749
+ },
+ {
+ "id": 3069632812797125
+ },
+ {
+ "id": 3069632270798021
+ },
+ {
+ "id": 3069625387584581
+ },
+ {
+ "id": 3069616536947781
+ },
+ {
+ "id": 3069615891254469
+ },
+ {
+ "id": 3069610912533701
+ },
+ {
+ "id": 3069610851683397
+ },
+ {
+ "id": 3069609531985221
+ },
+ {
+ "id": 3069603748252869
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3,
+ "records_with_pk": 3,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11841,
+ "records_with_pk": 11841,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "id": 3069634685308101
+ },
+ {
+ "id": 3069632810060997
+ },
+ {
+ "id": 3069632266996933
+ },
+ {
+ "id": 3069625385389125
+ },
+ {
+ "id": 3069616534391877
+ },
+ {
+ "id": 3069615889009861
+ },
+ {
+ "id": 3069610910289093
+ },
+ {
+ "id": 3069610849209413
+ },
+ {
+ "id": 3069609529527621
+ },
+ {
+ "id": 3069603744992453
+ },
+ {
+ "id": 3069589418200197
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17079,
+ "records_with_pk": 17079,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3069636080979269
+ },
+ {
+ "id": 3069635903065157
+ },
+ {
+ "id": 3069621694581893
+ },
+ {
+ "id": 3069619906513989
+ },
+ {
+ "id": 3069617265577285
+ },
+ {
+ "id": 3069598890986565
+ },
+ {
+ "id": 3069596124515461
+ },
+ {
+ "id": 3069593951833285
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2480,
+ "records_with_pk": 2480,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069634686274757
+ },
+ {
+ "id": 3069632267603141
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8216,
+ "records_with_pk": 8216,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3069625388289093
+ },
+ {
+ "id": 3069610913139909
+ },
+ {
+ "id": 3069610852518981
+ },
+ {
+ "id": 3069609532640581
+ },
+ {
+ "id": 3069603748859077
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 102,
+ "records_with_pk": 102,
+ "missing": 77,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069647316765765
+ },
+ {
+ "sitegoodsstockid": 3069647239007557
+ },
+ {
+ "sitegoodsstockid": 3069646941146245
+ },
+ {
+ "sitegoodsstockid": 3069646857063493
+ },
+ {
+ "sitegoodsstockid": 3069646766230853
+ },
+ {
+ "sitegoodsstockid": 3069646432160965
+ },
+ {
+ "sitegoodsstockid": 3069646279117893
+ },
+ {
+ "sitegoodsstockid": 3069646166576453
+ },
+ {
+ "sitegoodsstockid": 3069646048906309
+ },
+ {
+ "sitegoodsstockid": 3069645956992197
+ },
+ {
+ "sitegoodsstockid": 3069645885213829
+ },
+ {
+ "sitegoodsstockid": 3069645802638534
+ },
+ {
+ "sitegoodsstockid": 3069645719981253
+ },
+ {
+ "sitegoodsstockid": 3069645641927877
+ },
+ {
+ "sitegoodsstockid": 3069645553847365
+ },
+ {
+ "sitegoodsstockid": 3069645483248709
+ },
+ {
+ "sitegoodsstockid": 3069645384633413
+ },
+ {
+ "sitegoodsstockid": 3069645313461573
+ },
+ {
+ "sitegoodsstockid": 3069645232803141
+ },
+ {
+ "sitegoodsstockid": 3069645148966085
+ },
+ {
+ "sitegoodsstockid": 3069645055986821
+ },
+ {
+ "sitegoodsstockid": 3069644967644229
+ },
+ {
+ "sitegoodsstockid": 3069644878597445
+ },
+ {
+ "sitegoodsstockid": 3069644774067269
+ },
+ {
+ "sitegoodsstockid": 3069644673993925
+ },
+ {
+ "sitegoodsstockid": 3069644316544325
+ },
+ {
+ "sitegoodsstockid": 3069644213062725
+ },
+ {
+ "sitegoodsstockid": 3069644132584581
+ },
+ {
+ "sitegoodsstockid": 3069643942022277
+ },
+ {
+ "sitegoodsstockid": 3069643843013957
+ },
+ {
+ "sitegoodsstockid": 3069643746888773
+ },
+ {
+ "sitegoodsstockid": 3069643655285957
+ },
+ {
+ "sitegoodsstockid": 3069643359669573
+ },
+ {
+ "sitegoodsstockid": 3069643135929669
+ },
+ {
+ "sitegoodsstockid": 3069642950970501
+ },
+ {
+ "sitegoodsstockid": 3069642870164549
+ },
+ {
+ "sitegoodsstockid": 3069642795175237
+ },
+ {
+ "sitegoodsstockid": 3069642711796869
+ },
+ {
+ "sitegoodsstockid": 3069642615573637
+ },
+ {
+ "sitegoodsstockid": 3069638189976773
+ },
+ {
+ "sitegoodsstockid": 3069637297311045
+ },
+ {
+ "sitegoodsstockid": 3069637298294085
+ },
+ {
+ "sitegoodsstockid": 3069637300718917
+ },
+ {
+ "sitegoodsstockid": 3069637295361349
+ },
+ {
+ "sitegoodsstockid": 3069637298769221
+ },
+ {
+ "sitegoodsstockid": 3069637299752261
+ },
+ {
+ "sitegoodsstockid": 3069637295902021
+ },
+ {
+ "sitegoodsstockid": 3069637296377157
+ },
+ {
+ "sitegoodsstockid": 3069637296835909
+ },
+ {
+ "sitegoodsstockid": 3069637297818949
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1748,
+ "records_with_pk": 1748,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3069634689305797
+ },
+ {
+ "id": 3069615891860677
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 27,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 27,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 127,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T21:47:07.780539+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18511,
+ "diff": -18510
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 20,
+ "diff": -20
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 172,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23482,
+ "diff": -116
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23482,
+ "diff": -116
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 20,
+ "diff": -20
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 26.77,
+ "diff": -26.77
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 624.0,
+ "diff": -624.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1585.37,
+ "diff": -1585.37
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 390.03,
+ "diff": -390.03
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 544.57,
+ "diff": -544.57
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18511,
+ "diff": -125
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2872,
+ "diff": -23
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 332894.07,
+ "diff": -3289.6300000000047
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2872,
+ "diff": -23
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 3,
+ "diff": -3
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 449.47,
+ "diff": -449.47
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5033,
+ "diff": -30
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4782,
+ "diff": -37
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4782,
+ "diff": -37
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 13,
+ "diff": -13
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 720.0,
+ "diff": -720.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 624.0,
+ "diff": -624.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11514,
+ "diff": -87
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 18,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 1262.0,
+ "diff": -1262.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17071,
+ "diff": -94
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 16,
+ "diff": -16
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 327.0,
+ "diff": -327.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19278
+ },
+ "generated_at": "2026-01-27T21:47:17.800036+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 127,
+ "total_errors": 0
+ },
+ "total_missing": 127,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T21:47:17.800057+08:00"
+}
diff --git a/etl_billiards/reports/data_integrity_window_20260127_221542.json b/etl_billiards/reports/data_integrity_window_20260127_221542.json
new file mode 100644
index 0000000..a84d8b1
--- /dev/null
+++ b/etl_billiards/reports/data_integrity_window_20260127_221542.json
@@ -0,0 +1,1447 @@
+{
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T18:13:11+08:00",
+ "end": "2026-01-28T00:13:11+08:00",
+ "segments": 1
+ },
+ "windows": [
+ {
+ "mode": "window",
+ "window": {
+ "start": "2026-01-27T18:13:11+08:00",
+ "end": "2026-01-28T00:13:11+08:00",
+ "label": "segment_1",
+ "granularity": "window"
+ },
+ "api_to_ods": {
+ "window_split_unit": "none",
+ "window_compensation_hours": 0,
+ "start": "2026-01-27T18:13:11+08:00",
+ "end": "2026-01-28T00:13:11+08:00",
+ "cutoff": null,
+ "window_days": 0,
+ "window_hours": 6,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 69,
+ "records_with_pk": 69,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3069672327105733
+ },
+ {
+ "id": 3069668445244741
+ },
+ {
+ "id": 3069660125908037
+ },
+ {
+ "id": 3069660077477189
+ },
+ {
+ "id": 3069658923797829
+ },
+ {
+ "id": 3069656707599685
+ },
+ {
+ "id": 3069656571120837
+ },
+ {
+ "id": 3069655684402501
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 10020,
+ "records_with_pk": 10020,
+ "missing": 7,
+ "missing_samples": [
+ {
+ "id": 3069672345636165
+ },
+ {
+ "id": 3069668463955141
+ },
+ {
+ "id": 3069660143471813
+ },
+ {
+ "id": 3069660096826502
+ },
+ {
+ "id": 3069658966068421
+ },
+ {
+ "id": 3069656724704453
+ },
+ {
+ "id": 3069655700786245
+ }
+ ],
+ "pages": 51,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4,
+ "records_with_pk": 4,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11849,
+ "records_with_pk": 11849,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3069672343391557
+ },
+ {
+ "id": 3069668461464773
+ },
+ {
+ "id": 3069660138605765
+ },
+ {
+ "id": 3069660094221445
+ },
+ {
+ "id": 3069658963610821
+ },
+ {
+ "id": 3069656722115781
+ },
+ {
+ "id": 3069656593992901
+ },
+ {
+ "id": 3069655698476101
+ }
+ ],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 38,
+ "records_with_pk": 38,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 17083,
+ "records_with_pk": 17083,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3069661327215685
+ },
+ {
+ "id": 3069661208513733
+ },
+ {
+ "id": 3069656847420485
+ },
+ {
+ "id": 3069655803350085
+ }
+ ],
+ "pages": 86,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 556,
+ "records_with_pk": 556,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 945,
+ "records_with_pk": 945,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2480,
+ "records_with_pk": 2480,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8224,
+ "records_with_pk": 8224,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "id": 3069672346307909
+ },
+ {
+ "id": 3069672346307910
+ },
+ {
+ "id": 3069668464790725
+ },
+ {
+ "id": 3069660144274629
+ },
+ {
+ "id": 3069660097432709
+ },
+ {
+ "id": 3069658966740165
+ },
+ {
+ "id": 3069656725621957
+ },
+ {
+ "id": 3069655701539909
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 186,
+ "records_with_pk": 186,
+ "missing": 98,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3069675336060101
+ },
+ {
+ "sitegoodsstockid": 3069675258055877
+ },
+ {
+ "sitegoodsstockid": 3069675188227141
+ },
+ {
+ "sitegoodsstockid": 3069675118201989
+ },
+ {
+ "sitegoodsstockid": 3069675038903365
+ },
+ {
+ "sitegoodsstockid": 3069674956164229
+ },
+ {
+ "sitegoodsstockid": 3069674877848645
+ },
+ {
+ "sitegoodsstockid": 3069674676948101
+ },
+ {
+ "sitegoodsstockid": 3069674677423237
+ },
+ {
+ "sitegoodsstockid": 3069674677881989
+ },
+ {
+ "sitegoodsstockid": 3069674678406277
+ },
+ {
+ "sitegoodsstockid": 3069674675997829
+ },
+ {
+ "sitegoodsstockid": 3069674678881413
+ },
+ {
+ "sitegoodsstockid": 3069674676472965
+ },
+ {
+ "sitegoodsstockid": 3069674679422085
+ },
+ {
+ "sitegoodsstockid": 3069674679946373
+ },
+ {
+ "sitegoodsstockid": 3069674674211973
+ },
+ {
+ "sitegoodsstockid": 3069674675522693
+ },
+ {
+ "sitegoodsstockid": 3069674675031173
+ },
+ {
+ "sitegoodsstockid": 3069665853377733
+ },
+ {
+ "sitegoodsstockid": 3069665852886213
+ },
+ {
+ "sitegoodsstockid": 3069665852378309
+ },
+ {
+ "sitegoodsstockid": 3069658907364485
+ },
+ {
+ "sitegoodsstockid": 3069656595631301
+ },
+ {
+ "sitegoodsstockid": 3069655272918085
+ },
+ {
+ "sitegoodsstockid": 3069655264988229
+ },
+ {
+ "sitegoodsstockid": 3069655265446981
+ },
+ {
+ "sitegoodsstockid": 3069655266430021
+ },
+ {
+ "sitegoodsstockid": 3069655268002885
+ },
+ {
+ "sitegoodsstockid": 3069655269575749
+ },
+ {
+ "sitegoodsstockid": 3069655270034501
+ },
+ {
+ "sitegoodsstockid": 3069655273917509
+ },
+ {
+ "sitegoodsstockid": 3069655265922117
+ },
+ {
+ "sitegoodsstockid": 3069655270509637
+ },
+ {
+ "sitegoodsstockid": 3069655270984773
+ },
+ {
+ "sitegoodsstockid": 3069655271967813
+ },
+ {
+ "sitegoodsstockid": 3069655273409605
+ },
+ {
+ "sitegoodsstockid": 3069655267445829
+ },
+ {
+ "sitegoodsstockid": 3069655271459909
+ },
+ {
+ "sitegoodsstockid": 3069655272442949
+ },
+ {
+ "sitegoodsstockid": 3069655268510789
+ },
+ {
+ "sitegoodsstockid": 3069655269035077
+ },
+ {
+ "sitegoodsstockid": 3069655266905158
+ },
+ {
+ "sitegoodsstockid": 3069652056247621
+ },
+ {
+ "sitegoodsstockid": 3069651495046277
+ },
+ {
+ "sitegoodsstockid": 3069651397299269
+ },
+ {
+ "sitegoodsstockid": 3069651293899909
+ },
+ {
+ "sitegoodsstockid": 3069651224481093
+ },
+ {
+ "sitegoodsstockid": 3069651140676741
+ },
+ {
+ "sitegoodsstockid": 3069651040636229
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 171,
+ "records_with_pk": 171,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1748,
+ "records_with_pk": 1748,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 172,
+ "records_with_pk": 172,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 37,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 37,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 133,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T22:15:33.215615+08:00"
+ },
+ "ods_to_dwd": {
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 1,
+ "ods": 18521,
+ "diff": -18520
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 31,
+ "diff": -31
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 69,
+ "ods": 69,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 556,
+ "ods": 556,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 945,
+ "ods": 945,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 413038.35,
+ "ods_sum": 413038.35,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 1,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 171,
+ "ods": 172,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 170,
+ "ods": 171,
+ "diff": -1
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 34,
+ "ods": 34,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23494,
+ "diff": -128
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 23366,
+ "ods": 23494,
+ "diff": -128
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 31,
+ "diff": -31
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 265.76,
+ "diff": -265.76
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1096.0,
+ "diff": -1096.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 2668.81,
+ "diff": -2668.81
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 479.64,
+ "diff": -479.64
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 827.41,
+ "diff": -827.41
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 18386,
+ "ods": 18521,
+ "diff": -135
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2874,
+ "diff": -25
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 329604.44,
+ "ods_sum": 333104.06,
+ "diff": -3499.6199999999953
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 2849,
+ "ods": 2874,
+ "diff": -25
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 17563,
+ "ods": 17563,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 21673.2,
+ "ods_sum": 21673.2,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 4,
+ "diff": -4
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 543.6,
+ "diff": -543.6
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 5003,
+ "ods": 5033,
+ "diff": -30
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 414.17,
+ "ods_sum": 414.17,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 98,
+ "ods": 98,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4784,
+ "diff": -39
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 4745,
+ "ods": 4784,
+ "diff": -39
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 18,
+ "diff": -18
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 1288.0,
+ "diff": -1288.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 1096.0,
+ "diff": -1096.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 11427,
+ "ods": 11519,
+ "diff": -92
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 7544.8,
+ "ods_sum": 7544.8,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": true,
+ "window_col": "create_time",
+ "count": {
+ "dwd": 0,
+ "ods": 31,
+ "diff": -31
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 2416.0,
+ "diff": -2416.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 16977,
+ "ods": 17079,
+ "diff": -102
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 455,
+ "ods": 457,
+ "diff": -2
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 29,
+ "diff": -29
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 421.0,
+ "diff": -421.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": true,
+ "window_col": "pay_time",
+ "count": {
+ "dwd": 0,
+ "ods": 0,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "windowed": false,
+ "window_col": null,
+ "count": {
+ "dwd": 45,
+ "ods": 45,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "total_count_diff": -19398
+ },
+ "generated_at": "2026-01-27T22:15:42.699870+08:00"
+ }
+ ],
+ "api_to_ods": {
+ "total_missing": 133,
+ "total_errors": 0
+ },
+ "total_missing": 133,
+ "total_errors": 0,
+ "generated_at": "2026-01-27T22:15:42.699967+08:00"
+}
diff --git a/etl_billiards/reports/dwd_quality_report.json b/etl_billiards/reports/dwd_quality_report.json
new file mode 100644
index 0000000..9480eb5
--- /dev/null
+++ b/etl_billiards/reports/dwd_quality_report.json
@@ -0,0 +1,692 @@
+{
+ "generated_at": "2025-12-09T05:21:24.745244",
+ "tables": [
+ {
+ "dwd_table": "billiards_dwd.dim_site",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 1,
+ "ods": 200,
+ "diff": -199
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_site_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 1,
+ "ods": 200,
+ "diff": -199
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table",
+ "ods_table": "billiards_ods.site_tables_master",
+ "count": {
+ "dwd": 71,
+ "ods": 71,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_table_ex",
+ "ods_table": "billiards_ods.site_tables_master",
+ "count": {
+ "dwd": 71,
+ "ods": 71,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "count": {
+ "dwd": 50,
+ "ods": 50,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_assistant_ex",
+ "ods_table": "billiards_ods.assistant_accounts_master",
+ "count": {
+ "dwd": 50,
+ "ods": 50,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member",
+ "ods_table": "billiards_ods.member_profiles",
+ "count": {
+ "dwd": 199,
+ "ods": 199,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_ex",
+ "ods_table": "billiards_ods.member_profiles",
+ "count": {
+ "dwd": 199,
+ "ods": 199,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance",
+ "dwd_sum": 31061.03,
+ "ods_sum": 31061.03,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_member_card_account_ex",
+ "ods_table": "billiards_ods.member_stored_value_cards",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "deliveryfeededuct",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "count": {
+ "dwd": 156,
+ "ods": 156,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_tenant_goods_ex",
+ "ods_table": "billiards_ods.tenant_goods_master",
+ "count": {
+ "dwd": 156,
+ "ods": 156,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods",
+ "ods_table": "billiards_ods.store_goods_master",
+ "count": {
+ "dwd": 161,
+ "ods": 161,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_store_goods_ex",
+ "ods_table": "billiards_ods.store_goods_master",
+ "count": {
+ "dwd": 161,
+ "ods": 161,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_goods_category",
+ "ods_table": "billiards_ods.stock_goods_category_tree",
+ "count": {
+ "dwd": 26,
+ "ods": 9,
+ "diff": 17
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dim_groupbuy_package_ex",
+ "ods_table": "billiards_ods.group_buy_packages",
+ "count": {
+ "dwd": 17,
+ "ods": 17,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head",
+ "ods_table": "billiards_ods.settlement_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_settlement_head_ex",
+ "ods_table": "billiards_ods.settlement_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "adjust_amount",
+ "dwd_sum": 1157.45,
+ "ods_sum": 1157.45,
+ "diff": 0.0
+ },
+ {
+ "column": "coupon_promotion_amount",
+ "dwd_sum": 11244.49,
+ "ods_sum": 11244.49,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 18107.0,
+ "ods_sum": 18107.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 1149.19,
+ "ods_sum": 1149.19,
+ "diff": 0.0
+ },
+ {
+ "column": "real_table_charge_money",
+ "dwd_sum": 5705.06,
+ "ods_sum": 5705.06,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_log_ex",
+ "ods_table": "billiards_ods.table_fee_transactions",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "fee_total",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "mgmt_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "used_card_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 20650.84,
+ "ods_sum": 20650.84,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_table_fee_adjust_ex",
+ "ods_table": "billiards_ods.table_fee_discount_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "cost_money",
+ "dwd_sum": 22.3,
+ "ods_sum": 22.3,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 4583.0,
+ "ods_sum": 4583.0,
+ "diff": 0.0
+ },
+ {
+ "column": "real_goods_money",
+ "dwd_sum": 3791.0,
+ "ods_sum": 3791.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_store_goods_sale_ex",
+ "ods_table": "billiards_ods.store_goods_sales_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "discount_money",
+ "dwd_sum": 792.0,
+ "ods_sum": 792.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_coupon_deduct_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "option_member_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "point_discount_money_cost",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "push_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_deduct_money",
+ "dwd_sum": 626.83,
+ "ods_sum": 626.83,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 63251.37,
+ "ods_sum": 63251.37,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_service_log_ex",
+ "ods_table": "billiards_ods.assistant_service_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "manual_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "member_discount_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "service_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "count": {
+ "dwd": 15,
+ "ods": 15,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_assistant_trash_event_ex",
+ "ods_table": "billiards_ods.assistant_cancellation_records",
+ "count": {
+ "dwd": 15,
+ "ods": 15,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_member_balance_change_ex",
+ "ods_table": "billiards_ods.member_balance_changes",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 12266.0,
+ "ods_sum": 12266.0,
+ "diff": 0.0
+ },
+ {
+ "column": "ledger_amount",
+ "dwd_sum": 12049.53,
+ "ods_sum": 12049.53,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_groupbuy_redemption_ex",
+ "ods_table": "billiards_ods.group_buy_redemption_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "assistant_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "assistant_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "goods_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "recharge_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "reward_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "table_service_promotion_money",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "coupon_money",
+ "dwd_sum": 11956.0,
+ "ods_sum": 11956.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_platform_coupon_redemption_ex",
+ "ods_table": "billiards_ods.platform_coupon_redemption_records",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_recharge_order_ex",
+ "ods_table": "billiards_ods.recharge_settlements",
+ "count": {
+ "dwd": 74,
+ "ods": 74,
+ "diff": 0
+ },
+ "amounts": []
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_payment",
+ "ods_table": "billiards_ods.payment_transactions",
+ "count": {
+ "dwd": 200,
+ "ods": 200,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "pay_amount",
+ "dwd_sum": 10863.0,
+ "ods_sum": 10863.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund",
+ "ods_table": "billiards_ods.refund_transactions",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "channel_fee",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "pay_amount",
+ "dwd_sum": -62186.0,
+ "ods_sum": -62186.0,
+ "diff": 0.0
+ }
+ ]
+ },
+ {
+ "dwd_table": "billiards_dwd.dwd_refund_ex",
+ "ods_table": "billiards_ods.refund_transactions",
+ "count": {
+ "dwd": 11,
+ "ods": 11,
+ "diff": 0
+ },
+ "amounts": [
+ {
+ "column": "balance_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "card_frozen_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "refund_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ },
+ {
+ "column": "round_amount",
+ "dwd_sum": 0.0,
+ "ods_sum": 0.0,
+ "diff": 0.0
+ }
+ ]
+ }
+ ],
+ "note": "行数/金额核对,金额字段基于列名包含 amount/money/fee/balance 的数值列自动扫描。"
+}
\ No newline at end of file
diff --git a/etl_billiards/reports/loyal_billiards_customers_2025-12-26.csv b/etl_billiards/reports/loyal_billiards_customers_2025-12-26.csv
new file mode 100644
index 0000000..538861b
--- /dev/null
+++ b/etl_billiards/reports/loyal_billiards_customers_2025-12-26.csv
@@ -0,0 +1,51 @@
+排名,客户姓名,联系方式,单次日打球小时数,到店平均间隔(天),10-12月来店次数,最后一次到店日期
+1,黄生,13609719719,7.53,1.8,43,2025-12-24 14:51
+2,曾巧明,18688471488,6.25,1.2,71,2025-12-25 15:49
+3,葛先生,13811638071,5.81,1.3,39,2025-12-26 00:55
+4,孟紫龙,17631643741,4.73,1.5,17,2025-12-23 16:27
+5,桂先生,16676777275,4.70,2.3,25,2025-12-16 19:05
+6,孟紫龙(该会员已注销),17631643741(1),4.64,2.0,6,2025-10-13 18:57
+7,陈先生,13922200419,3.92,,1,2025-10-18 12:35
+8,候,13161960323,3.67,1.0,6,2025-12-17 23:13
+9,小燕,17802081334,3.58,1.2,29,2025-12-22 20:10
+10,陈先生,15915782829,3.48,,1,2025-11-07 00:44
+11,牛先生,15201265159,3.44,1.0,3,2025-11-24 17:10
+12,李先生,13427574343,3.39,2.8,14,2025-12-24 22:49
+13,汪先生,13925126339,3.34,1.0,2,2025-10-08 20:59
+14,林先生,13342871070,3.30,,1,2025-12-05 15:52
+15,桂先生(该会员已注销),16676777275(1),3.17,2.0,6,2025-10-16 19:37
+16,贺斌,15017500885,3.15,3.0,3,2025-11-03 18:42
+17,谢俊,18620395198,3.09,1.6,53,2025-12-22 20:03
+18,郑先生,15902794331,3.01,1.7,12,2025-12-10 22:12
+19,周先生,19350986822,2.92,2.0,11,2025-12-26 02:06
+20,王先生,18520321125,2.91,6.0,2,2025-12-02 21:00
+21,胡先生,18620043391,2.89,8.0,4,2025-12-01 19:01
+22,罗先生,13924036996,2.85,1.3,65,2025-12-25 22:25
+23,刘女士,17727637538,2.80,,1,2025-10-14 18:24
+24,魏先生,13726266862,2.70,1.0,2,2025-12-05 22:18
+25,吴生,13600453341,2.60,6.1,14,2025-12-25 17:51
+26,王先生,18302299763,2.58,,1,2025-12-24 18:30
+27,梅,13672464552,2.47,,1,2025-11-22 20:29
+28,郭先生,15622365001,2.43,3.5,3,2025-11-01 20:06
+29,艾宇民,15062279958,2.40,1.7,47,2025-12-25 20:28
+30,阿亮,15920462628,2.40,2.0,7,2025-12-04 20:05
+31,林先生,13763388785,2.39,2.0,6,2025-12-02 19:48
+32,李先生,13128264000,2.36,1.8,5,2025-11-07 23:01
+33,陈腾鑫,17817318218,2.35,1.5,50,2025-12-12 21:39
+34,昌哥,13798811229,2.27,16.0,2,2025-12-07 21:05
+35,张先生,13902258852,2.20,2.0,43,2025-12-24 18:42
+36,黄先生,13570163507,2.20,4.0,22,2025-12-24 15:58
+37,陈德韩,13431017864,2.18,4.2,6,2025-10-26 19:59
+38,罗先生,13922289222,2.16,9.4,6,2025-11-26 18:54
+39,陈世,13430271938,2.15,24.5,3,2025-11-20 21:45
+40,T,18028579962,2.14,6.9,9,2025-12-18 17:36
+41,大G,18680114598,2.10,1.0,2,2025-12-02 20:53
+42,卢广贤,18613066220,2.08,14.8,5,2025-12-13 15:27
+43,叶总,13711223287,2.08,1.5,7,2025-10-27 20:57
+44,杜先生,18826454705,2.03,,1,2025-11-02 20:12
+45,谭先生,13824473185,2.03,,1,2025-10-20 17:15
+46,杨,13066365960,2.00,2.0,2,2025-12-05 19:28
+47,小熊,13927020145,1.94,9.5,3,2025-11-04 17:36
+48,曾先生,13316091235,1.92,10.1,8,2025-12-24 11:53
+49,游,17267866666,1.89,1.6,8,2025-12-07 17:36
+50,夏,19120942851,1.88,1.8,6,2025-11-06 18:05
diff --git a/etl_billiards/reports/loyal_billiards_customers_gap_lt_20d_2025-12-26.csv b/etl_billiards/reports/loyal_billiards_customers_gap_lt_20d_2025-12-26.csv
new file mode 100644
index 0000000..71cbf75
--- /dev/null
+++ b/etl_billiards/reports/loyal_billiards_customers_gap_lt_20d_2025-12-26.csv
@@ -0,0 +1,64 @@
+排名,客户姓名,联系方式,单次日打球小时数,到店平均间隔(天),10-12月来店次数,最后一次到店日期
+1,黄生,13609719719,7.53,1.8,43,2025-12-24 14:51
+2,曾巧明,18688471488,6.25,1.2,71,2025-12-25 15:49
+3,葛先生,13811638071,5.81,1.3,39,2025-12-26 00:55
+4,孟紫龙,17631643741,4.73,1.5,17,2025-12-23 16:27
+5,桂先生,16676777275,4.70,2.3,25,2025-12-16 19:05
+6,孟紫龙(该会员已注销),17631643741(1),4.64,2.0,6,2025-10-13 18:57
+7,候,13161960323,3.67,1.0,6,2025-12-17 23:13
+8,小燕,17802081334,3.58,1.2,29,2025-12-22 20:10
+9,牛先生,15201265159,3.44,1.0,3,2025-11-24 17:10
+10,李先生,13427574343,3.39,2.8,14,2025-12-24 22:49
+11,汪先生,13925126339,3.34,1.0,2,2025-10-08 20:59
+12,桂先生(该会员已注销),16676777275(1),3.17,2.0,6,2025-10-16 19:37
+13,贺斌,15017500885,3.15,3.0,3,2025-11-03 18:42
+14,谢俊,18620395198,3.09,1.6,53,2025-12-22 20:03
+15,郑先生,15902794331,3.01,1.7,12,2025-12-10 22:12
+16,周先生,19350986822,2.92,2.0,11,2025-12-26 02:06
+17,王先生,18520321125,2.91,6.0,2,2025-12-02 21:00
+18,胡先生,18620043391,2.89,8.0,4,2025-12-01 19:01
+19,罗先生,13924036996,2.85,1.3,65,2025-12-25 22:25
+20,魏先生,13726266862,2.70,1.0,2,2025-12-05 22:18
+21,吴生,13600453341,2.60,6.1,14,2025-12-25 17:51
+22,郭先生,15622365001,2.43,3.5,3,2025-11-01 20:06
+23,艾宇民,15062279958,2.40,1.7,47,2025-12-25 20:28
+24,阿亮,15920462628,2.40,2.0,7,2025-12-04 20:05
+25,林先生,13763388785,2.39,2.0,6,2025-12-02 19:48
+26,李先生,13128264000,2.36,1.8,5,2025-11-07 23:01
+27,陈腾鑫,17817318218,2.35,1.5,50,2025-12-12 21:39
+28,昌哥,13798811229,2.27,16.0,2,2025-12-07 21:05
+29,张先生,13902258852,2.20,2.0,43,2025-12-24 18:42
+30,黄先生,13570163507,2.20,4.0,22,2025-12-24 15:58
+31,陈德韩,13431017864,2.18,4.2,6,2025-10-26 19:59
+32,罗先生,13922289222,2.16,9.4,6,2025-11-26 18:54
+33,T,18028579962,2.14,6.9,9,2025-12-18 17:36
+34,大G,18680114598,2.10,1.0,2,2025-12-02 20:53
+35,卢广贤,18613066220,2.08,14.8,5,2025-12-13 15:27
+36,叶总,13711223287,2.08,1.5,7,2025-10-27 20:57
+37,杨,13066365960,2.00,2.0,2,2025-12-05 19:28
+38,小熊,13927020145,1.94,9.5,3,2025-11-04 17:36
+39,曾先生,13316091235,1.92,10.1,8,2025-12-24 11:53
+40,游,17267866666,1.89,1.6,8,2025-12-07 17:36
+41,夏,19120942851,1.88,1.8,6,2025-11-06 18:05
+42,胡总,13385143091,1.86,1.0,2,2025-12-20 21:00
+43,轩哥,18826267530,1.85,3.2,25,2025-12-18 02:11
+44,常总,18570077188,1.84,4.0,3,2025-12-22 19:21
+45,歌神,18819262164,1.75,2.0,3,2025-10-24 21:47
+46,君姐,16624614594,1.66,1.0,2,2025-11-27 21:22
+47,叶先生,13826479539,1.60,7.3,10,2025-12-05 23:07
+48,江先生,18819484838,1.52,5.1,15,2025-12-13 19:24
+49,黄先生,15818822109,1.48,7.8,7,2025-12-17 00:58
+50,张先生,13682854528,1.48,2.0,2,2025-12-19 22:37
+51,陶,18924022151,1.41,2.2,6,2025-10-26 23:52
+52,林总,13808881180,1.40,10.3,4,2025-12-24 19:18
+53,林先生,18826220332,1.36,17.7,4,2025-12-24 00:28
+54,李,13189179882,1.33,9.2,6,2025-11-24 12:38
+55,张丹逸,13609066637,1.20,1.0,2,2025-10-06 22:47
+56,罗超杰,13711268012,1.06,4.7,7,2025-11-05 15:50
+57,小宇,18745728077,1.03,10.0,2,2025-10-13 16:24
+58,蔡总,15914338893,1.01,3.1,17,2025-12-24 00:30
+59,羊,18785445094,0.99,3.0,9,2025-11-23 19:27
+60,林志铭,13570304233,0.98,13.0,2,2025-11-30 16:19
+61,钟智豪,18814002803,0.88,1.0,2,2025-11-28 23:50
+62,明哥,16620040999,0.66,5.5,3,2025-12-09 22:42
+63,冯先生,15588690348,0.46,1.0,2,2025-10-31 23:34
diff --git a/etl_billiards/reports/loyal_billiards_customers_report.py b/etl_billiards/reports/loyal_billiards_customers_report.py
new file mode 100644
index 0000000..975ea81
--- /dev/null
+++ b/etl_billiards/reports/loyal_billiards_customers_report.py
@@ -0,0 +1,340 @@
+# -*- coding: utf-8 -*-
+"""
+统计“忠实台球类竞技客户”Top N(按平均单次日打球小时数排序)。
+
+口径(默认):
+- 时间范围:2025-10-01 至今(可传参覆盖)
+- 仅统计 member_id != 0 且有时长的客户
+- 台桌区域仅包含:A区、B区、C区、VIP包厢、斯诺克区、TV台
+- 同日同一客户若同时开多台:按时间区间并集计时(不重复叠加)
+- “单次日打球小时数” = (时间范围内每日打球总小时数) / (有打球的日数)
+- “到店平均间(天)” = 相邻来店日的平均间隔天数(来店日数<2 则为空)
+- “10-12月来店次数” = 时间范围内来店日数(按日去重)
+- “最后一次到店日期” = 该客户最后一次开台的 start_use_time(精确到分钟)
+
+输出:CSV(UTF-8-SIG,便于 Excel 打开)
+"""
+
+from __future__ import annotations
+
+import argparse
+import csv
+from dataclasses import dataclass
+from datetime import date, datetime, time, timedelta
+from pathlib import Path
+from typing import Iterable
+from zoneinfo import ZoneInfo
+
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+
+
+DEFAULT_AREAS = ("A区", "B区", "C区", "VIP包厢", "斯诺克区", "TV台")
+
+
+@dataclass(frozen=True)
+class SessionRow:
+ member_id: int
+ start: datetime
+ end: datetime
+ area_name: str | None
+
+
+@dataclass(frozen=True)
+class MemberAgg:
+ member_id: int
+ total_hours: float
+ visit_days: int
+ avg_daily_hours: float
+ avg_gap_days: float | None
+ last_visit_at: datetime | None
+
+
+def _as_tz(dt: datetime, tz: ZoneInfo) -> datetime:
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=tz)
+ return dt.astimezone(tz)
+
+
+def _parse_date(s: str) -> date:
+ s = (s or "").strip()
+ if len(s) >= 10:
+ s = s[:10]
+ return date.fromisoformat(s)
+
+
+def _date_floor(dt: datetime, tz: ZoneInfo) -> datetime:
+ dt = _as_tz(dt, tz)
+ return datetime.combine(dt.date(), time.min).replace(tzinfo=tz)
+
+
+def _split_by_day(start: datetime, end: datetime, tz: ZoneInfo) -> Iterable[tuple[date, datetime, datetime]]:
+ start = _as_tz(start, tz)
+ end = _as_tz(end, tz)
+ if end <= start:
+ return []
+ cur = start
+ out: list[tuple[date, datetime, datetime]] = []
+ while True:
+ day_end = _date_floor(cur, tz) + timedelta(days=1)
+ seg_end = end if end <= day_end else day_end
+ out.append((cur.date(), cur, seg_end))
+ if seg_end >= end:
+ break
+ cur = seg_end
+ return out
+
+
+def _union_seconds(intervals: list[tuple[datetime, datetime]], tz: ZoneInfo) -> int:
+ cleaned = []
+ for s, e in intervals:
+ s = _as_tz(s, tz)
+ e = _as_tz(e, tz)
+ if e > s:
+ cleaned.append((s, e))
+ if not cleaned:
+ return 0
+ cleaned.sort(key=lambda x: x[0])
+ total = 0
+ cur_s, cur_e = cleaned[0]
+ for s, e in cleaned[1:]:
+ if s <= cur_e:
+ if e > cur_e:
+ cur_e = e
+ else:
+ total += int((cur_e - cur_s).total_seconds())
+ cur_s, cur_e = s, e
+ total += int((cur_e - cur_s).total_seconds())
+ return total
+
+
+def _avg_gap_days(visit_dates: list[date]) -> float | None:
+ if len(visit_dates) < 2:
+ return None
+ visit_dates = sorted(set(visit_dates))
+ if len(visit_dates) < 2:
+ return None
+ gaps = [(b - a).days for a, b in zip(visit_dates, visit_dates[1:]) if (b - a).days > 0]
+ if not gaps:
+ return None
+ return sum(gaps) / len(gaps)
+
+
+def _load_sessions(
+ conn: DatabaseConnection,
+ *,
+ store_id: int,
+ tz: ZoneInfo,
+ start_dt: datetime,
+ end_dt: datetime,
+ areas: tuple[str, ...],
+) -> list[SessionRow]:
+ sql = """
+ SELECT
+ member_id,
+ start_use_time,
+ ledger_end_time,
+ real_table_use_seconds,
+ site_table_area_name
+ FROM billiards_dwd.dwd_table_fee_log
+ WHERE site_id = %s
+ AND member_id IS NOT NULL
+ AND member_id <> 0
+ AND start_use_time >= %s
+ AND start_use_time < %s
+ AND site_table_area_name = ANY(%s)
+ """
+ rows = conn.query(sql, (store_id, start_dt, end_dt, list(areas)))
+ sessions: list[SessionRow] = []
+ for r in rows:
+ member_id = int(r.get("member_id") or 0)
+ if member_id <= 0:
+ continue
+ start = r.get("start_use_time")
+ end = r.get("ledger_end_time")
+ if not isinstance(start, datetime):
+ continue
+ if isinstance(end, datetime):
+ pass
+ else:
+ secs = r.get("real_table_use_seconds")
+ try:
+ secs = int(secs or 0)
+ except Exception:
+ secs = 0
+ if secs > 0:
+ end = start + timedelta(seconds=secs)
+ else:
+ continue
+
+ start = _as_tz(start, tz)
+ end = _as_tz(end, tz)
+ if end <= start:
+ continue
+
+ sessions.append(SessionRow(member_id=member_id, start=start, end=end, area_name=r.get("site_table_area_name")))
+ return sessions
+
+
+def _load_member_profiles(conn: DatabaseConnection, member_ids: list[int]) -> dict[int, dict]:
+ if not member_ids:
+ return {}
+ sql = """
+ SELECT member_id, nickname, mobile
+ FROM billiards_dwd.dim_member
+ WHERE scd2_is_current = 1
+ AND member_id = ANY(%s)
+ """
+ rows = conn.query(sql, (member_ids,))
+ return {int(r["member_id"]): r for r in rows if r.get("member_id") is not None}
+
+
+def _load_latest_settlement_contact(conn: DatabaseConnection, *, store_id: int, member_ids: list[int]) -> dict[int, dict]:
+ if not member_ids:
+ return {}
+ sql = """
+ SELECT DISTINCT ON (member_id)
+ member_id, member_name, member_phone, pay_time
+ FROM billiards_dwd.dwd_settlement_head
+ WHERE site_id = %s
+ AND member_id = ANY(%s)
+ AND member_id <> 0
+ ORDER BY member_id, pay_time DESC NULLS LAST
+ """
+ rows = conn.query(sql, (store_id, member_ids))
+ return {int(r["member_id"]): r for r in rows if r.get("member_id") is not None}
+
+
+def _build_member_aggs(sessions: list[SessionRow], tz: ZoneInfo) -> list[MemberAgg]:
+ by_member_day: dict[int, dict[date, list[tuple[datetime, datetime]]]] = {}
+ last_visit_at: dict[int, datetime] = {}
+
+ for s in sessions:
+ if s.member_id not in last_visit_at or s.start > last_visit_at[s.member_id]:
+ last_visit_at[s.member_id] = s.start
+ for d, seg_s, seg_e in _split_by_day(s.start, s.end, tz):
+ by_member_day.setdefault(s.member_id, {}).setdefault(d, []).append((seg_s, seg_e))
+
+ aggs: list[MemberAgg] = []
+ for member_id, day_map in by_member_day.items():
+ day_seconds = {d: _union_seconds(iv, tz) for d, iv in day_map.items()}
+ day_seconds = {d: sec for d, sec in day_seconds.items() if sec > 0}
+ if not day_seconds:
+ continue
+ visit_dates = sorted(day_seconds.keys())
+ total_hours = sum(day_seconds.values()) / 3600.0
+ visit_days = len(visit_dates)
+ avg_daily_hours = total_hours / visit_days if visit_days else 0.0
+ aggs.append(
+ MemberAgg(
+ member_id=member_id,
+ total_hours=float(total_hours),
+ visit_days=int(visit_days),
+ avg_daily_hours=float(avg_daily_hours),
+ avg_gap_days=_avg_gap_days(visit_dates),
+ last_visit_at=last_visit_at.get(member_id),
+ )
+ )
+
+ return aggs
+
+
+def _write_report(
+ out_path: Path,
+ *,
+ rows: list[MemberAgg],
+ tz: ZoneInfo,
+ dim_profiles: dict[int, dict],
+ latest_settle: dict[int, dict],
+):
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ with out_path.open("w", encoding="utf-8-sig", newline="") as f:
+ w = csv.writer(f)
+ w.writerow(["排名", "客户姓名", "联系方式", "单次日打球小时数", "到店平均间隔(天)", "10-12月来店次数", "最后一次到店日期"])
+ for idx, row in enumerate(rows, start=1):
+ mid = int(row.member_id)
+ prof = dim_profiles.get(mid) or {}
+ settle = latest_settle.get(mid) or {}
+ name = settle.get("member_name") or prof.get("nickname") or ""
+ phone = settle.get("member_phone") or prof.get("mobile") or ""
+ last_visit_str = ""
+ if isinstance(row.last_visit_at, datetime):
+ last_visit_str = _as_tz(row.last_visit_at, tz).strftime("%Y-%m-%d %H:%M")
+ w.writerow(
+ [
+ idx,
+ str(name),
+ str(phone),
+ f"{float(row.avg_daily_hours or 0.0):.2f}",
+ "" if row.avg_gap_days is None else f"{float(row.avg_gap_days):.1f}",
+ int(row.visit_days or 0),
+ last_visit_str,
+ ]
+ )
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description="Loyal billiards customers report")
+ parser.add_argument("--start-date", default="2025-10-01", help="YYYY-MM-DD")
+ parser.add_argument("--end-date", default="", help="YYYY-MM-DD (default: today)")
+ parser.add_argument("--top-n", type=int, default=50)
+ parser.add_argument("--areas", default=",".join(DEFAULT_AREAS), help="comma separated")
+ parser.add_argument("--out", default="", help="output csv path")
+ args = parser.parse_args()
+
+ cfg = AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ store_id = int(cfg.get("app.store_id"))
+
+ start_date = _parse_date(args.start_date)
+ end_date = _parse_date(args.end_date) if args.end_date else datetime.now(tz).date()
+ if end_date < start_date:
+ raise SystemExit("end_date must be >= start_date")
+
+ start_dt = datetime.combine(start_date, time.min).replace(tzinfo=tz)
+ end_dt = datetime.combine(end_date + timedelta(days=1), time.min).replace(tzinfo=tz)
+
+ areas = tuple([a.strip() for a in str(args.areas or "").split(",") if a.strip()])
+ if not areas:
+ raise SystemExit("areas is empty")
+
+ conn = DatabaseConnection(dsn=cfg["db"]["dsn"], session=cfg["db"].get("session"))
+ try:
+ sessions = _load_sessions(conn, store_id=store_id, tz=tz, start_dt=start_dt, end_dt=end_dt, areas=areas)
+ aggs = _build_member_aggs(sessions, tz)
+ aggs.sort(key=lambda x: x.avg_daily_hours, reverse=True)
+ top_n = max(1, int(args.top_n))
+
+ picked_avg = aggs[:top_n]
+ picked_gap_lt_20 = [r for r in aggs if r.avg_gap_days is not None and r.avg_gap_days < 20]
+
+ picked_visit = sorted(aggs, key=lambda x: (x.visit_days, x.avg_daily_hours), reverse=True)[:top_n]
+ picked_hours = sorted(aggs, key=lambda x: (x.total_hours, x.avg_daily_hours), reverse=True)[:top_n]
+
+ member_ids = sorted({r.member_id for r in (picked_avg + picked_gap_lt_20 + picked_visit + picked_hours)})
+ dim_profiles = _load_member_profiles(conn, member_ids)
+ latest_settle = _load_latest_settlement_contact(conn, store_id=store_id, member_ids=member_ids)
+ finally:
+ conn.close()
+
+ today = datetime.now(tz).date()
+ base_dir = Path(args.out).parent if args.out else Path(__file__).parent
+ out_main = Path(args.out) if args.out else base_dir / f"loyal_billiards_customers_{today.isoformat()}.csv"
+ out_gap = base_dir / f"loyal_billiards_customers_gap_lt_20d_{today.isoformat()}.csv"
+ out_visit = base_dir / f"loyal_billiards_customers_top{top_n}_by_visit_days_{today.isoformat()}.csv"
+ out_hours = base_dir / f"loyal_billiards_customers_top{top_n}_by_total_hours_{today.isoformat()}.csv"
+
+ _write_report(out_main, rows=picked_avg, tz=tz, dim_profiles=dim_profiles, latest_settle=latest_settle)
+ _write_report(out_gap, rows=picked_gap_lt_20, tz=tz, dim_profiles=dim_profiles, latest_settle=latest_settle)
+ _write_report(out_visit, rows=picked_visit, tz=tz, dim_profiles=dim_profiles, latest_settle=latest_settle)
+ _write_report(out_hours, rows=picked_hours, tz=tz, dim_profiles=dim_profiles, latest_settle=latest_settle)
+
+ print(str(out_main))
+ print(str(out_gap))
+ print(str(out_visit))
+ print(str(out_hours))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/reports/loyal_billiards_customers_top50_by_total_hours_2025-12-26.csv b/etl_billiards/reports/loyal_billiards_customers_top50_by_total_hours_2025-12-26.csv
new file mode 100644
index 0000000..6efa253
--- /dev/null
+++ b/etl_billiards/reports/loyal_billiards_customers_top50_by_total_hours_2025-12-26.csv
@@ -0,0 +1,51 @@
+排名,客户姓名,联系方式,单次日打球小时数,到店平均间隔(天),10-12月来店次数,最后一次到店日期
+1,曾巧明,18688471488,6.25,1.2,71,2025-12-25 15:49
+2,黄生,13609719719,7.53,1.8,43,2025-12-24 14:51
+3,葛先生,13811638071,5.81,1.3,39,2025-12-26 00:55
+4,罗先生,13924036996,2.85,1.3,65,2025-12-25 22:25
+5,谢俊,18620395198,3.09,1.6,53,2025-12-22 20:03
+6,桂先生,16676777275,4.70,2.3,25,2025-12-16 19:05
+7,陈腾鑫,17817318218,2.35,1.5,50,2025-12-12 21:39
+8,艾宇民,15062279958,2.40,1.7,47,2025-12-25 20:28
+9,小燕,17802081334,3.58,1.2,29,2025-12-22 20:10
+10,张先生,13902258852,2.20,2.0,43,2025-12-24 18:42
+11,孟紫龙,17631643741,4.73,1.5,17,2025-12-23 16:27
+12,黄先生,13570163507,2.20,4.0,22,2025-12-24 15:58
+13,李先生,13427574343,3.39,2.8,14,2025-12-24 22:49
+14,轩哥,18826267530,1.85,3.2,25,2025-12-18 02:11
+15,吴生,13600453341,2.60,6.1,14,2025-12-25 17:51
+16,郑先生,15902794331,3.01,1.7,12,2025-12-10 22:12
+17,周先生,19350986822,2.92,2.0,11,2025-12-26 02:06
+18,孟紫龙(该会员已注销),17631643741(1),4.64,2.0,6,2025-10-13 18:57
+19,江先生,18819484838,1.52,5.1,15,2025-12-13 19:24
+20,候,13161960323,3.67,1.0,6,2025-12-17 23:13
+21,T,18028579962,2.14,6.9,9,2025-12-18 17:36
+22,桂先生(该会员已注销),16676777275(1),3.17,2.0,6,2025-10-16 19:37
+23,蔡总,15914338893,1.01,3.1,17,2025-12-24 00:30
+24,阿亮,15920462628,2.40,2.0,7,2025-12-04 20:05
+25,叶先生,13826479539,1.60,7.3,10,2025-12-05 23:07
+26,曾先生,13316091235,1.92,10.1,8,2025-12-24 11:53
+27,游,17267866666,1.89,1.6,8,2025-12-07 17:36
+28,叶总,13711223287,2.08,1.5,7,2025-10-27 20:57
+29,林先生,13763388785,2.39,2.0,6,2025-12-02 19:48
+30,陈德韩,13431017864,2.18,4.2,6,2025-10-26 19:59
+31,罗先生,13922289222,2.16,9.4,6,2025-11-26 18:54
+32,李先生,13128264000,2.36,1.8,5,2025-11-07 23:01
+33,胡先生,18620043391,2.89,8.0,4,2025-12-01 19:01
+34,夏,19120942851,1.88,1.8,6,2025-11-06 18:05
+35,卢广贤,18613066220,2.08,14.8,5,2025-12-13 15:27
+36,黄先生,15818822109,1.48,7.8,7,2025-12-17 00:58
+37,牛先生,15201265159,3.44,1.0,3,2025-11-24 17:10
+38,贺斌,15017500885,3.15,3.0,3,2025-11-03 18:42
+39,羊,18785445094,0.99,3.0,9,2025-11-23 19:27
+40,陶,18924022151,1.41,2.2,6,2025-10-26 23:52
+41,李,13189179882,1.33,9.2,6,2025-11-24 12:38
+42,罗超杰,13711268012,1.06,4.7,7,2025-11-05 15:50
+43,郭先生,15622365001,2.43,3.5,3,2025-11-01 20:06
+44,汪先生,13925126339,3.34,1.0,2,2025-10-08 20:59
+45,陈世,13430271938,2.15,24.5,3,2025-11-20 21:45
+46,王先生,18520321125,2.91,6.0,2,2025-12-02 21:00
+47,小熊,13927020145,1.94,9.5,3,2025-11-04 17:36
+48,林总,13808881180,1.40,10.3,4,2025-12-24 19:18
+49,常总,18570077188,1.84,4.0,3,2025-12-22 19:21
+50,林先生,18826220332,1.36,17.7,4,2025-12-24 00:28
diff --git a/etl_billiards/reports/loyal_billiards_customers_top50_by_visit_days_2025-12-26.csv b/etl_billiards/reports/loyal_billiards_customers_top50_by_visit_days_2025-12-26.csv
new file mode 100644
index 0000000..b0e4ce7
--- /dev/null
+++ b/etl_billiards/reports/loyal_billiards_customers_top50_by_visit_days_2025-12-26.csv
@@ -0,0 +1,51 @@
+排名,客户姓名,联系方式,单次日打球小时数,到店平均间隔(天),10-12月来店次数,最后一次到店日期
+1,曾巧明,18688471488,6.25,1.2,71,2025-12-25 15:49
+2,罗先生,13924036996,2.85,1.3,65,2025-12-25 22:25
+3,谢俊,18620395198,3.09,1.6,53,2025-12-22 20:03
+4,陈腾鑫,17817318218,2.35,1.5,50,2025-12-12 21:39
+5,艾宇民,15062279958,2.40,1.7,47,2025-12-25 20:28
+6,黄生,13609719719,7.53,1.8,43,2025-12-24 14:51
+7,张先生,13902258852,2.20,2.0,43,2025-12-24 18:42
+8,葛先生,13811638071,5.81,1.3,39,2025-12-26 00:55
+9,小燕,17802081334,3.58,1.2,29,2025-12-22 20:10
+10,桂先生,16676777275,4.70,2.3,25,2025-12-16 19:05
+11,轩哥,18826267530,1.85,3.2,25,2025-12-18 02:11
+12,黄先生,13570163507,2.20,4.0,22,2025-12-24 15:58
+13,孟紫龙,17631643741,4.73,1.5,17,2025-12-23 16:27
+14,蔡总,15914338893,1.01,3.1,17,2025-12-24 00:30
+15,江先生,18819484838,1.52,5.1,15,2025-12-13 19:24
+16,李先生,13427574343,3.39,2.8,14,2025-12-24 22:49
+17,吴生,13600453341,2.60,6.1,14,2025-12-25 17:51
+18,郑先生,15902794331,3.01,1.7,12,2025-12-10 22:12
+19,周先生,19350986822,2.92,2.0,11,2025-12-26 02:06
+20,叶先生,13826479539,1.60,7.3,10,2025-12-05 23:07
+21,T,18028579962,2.14,6.9,9,2025-12-18 17:36
+22,羊,18785445094,0.99,3.0,9,2025-11-23 19:27
+23,曾先生,13316091235,1.92,10.1,8,2025-12-24 11:53
+24,游,17267866666,1.89,1.6,8,2025-12-07 17:36
+25,阿亮,15920462628,2.40,2.0,7,2025-12-04 20:05
+26,叶总,13711223287,2.08,1.5,7,2025-10-27 20:57
+27,黄先生,15818822109,1.48,7.8,7,2025-12-17 00:58
+28,罗超杰,13711268012,1.06,4.7,7,2025-11-05 15:50
+29,孟紫龙(该会员已注销),17631643741(1),4.64,2.0,6,2025-10-13 18:57
+30,候,13161960323,3.67,1.0,6,2025-12-17 23:13
+31,桂先生(该会员已注销),16676777275(1),3.17,2.0,6,2025-10-16 19:37
+32,林先生,13763388785,2.39,2.0,6,2025-12-02 19:48
+33,陈德韩,13431017864,2.18,4.2,6,2025-10-26 19:59
+34,罗先生,13922289222,2.16,9.4,6,2025-11-26 18:54
+35,夏,19120942851,1.88,1.8,6,2025-11-06 18:05
+36,陶,18924022151,1.41,2.2,6,2025-10-26 23:52
+37,李,13189179882,1.33,9.2,6,2025-11-24 12:38
+38,李先生,13128264000,2.36,1.8,5,2025-11-07 23:01
+39,卢广贤,18613066220,2.08,14.8,5,2025-12-13 15:27
+40,胡先生,18620043391,2.89,8.0,4,2025-12-01 19:01
+41,林总,13808881180,1.40,10.3,4,2025-12-24 19:18
+42,林先生,18826220332,1.36,17.7,4,2025-12-24 00:28
+43,牛先生,15201265159,3.44,1.0,3,2025-11-24 17:10
+44,贺斌,15017500885,3.15,3.0,3,2025-11-03 18:42
+45,郭先生,15622365001,2.43,3.5,3,2025-11-01 20:06
+46,陈世,13430271938,2.15,24.5,3,2025-11-20 21:45
+47,小熊,13927020145,1.94,9.5,3,2025-11-04 17:36
+48,常总,18570077188,1.84,4.0,3,2025-12-22 19:21
+49,歌神,18819262164,1.75,2.0,3,2025-10-24 21:47
+50,明哥,16620040999,0.66,5.5,3,2025-12-09 22:42
diff --git a/etl_billiards/reports/loyal_customers_input_2025-12-26.txt b/etl_billiards/reports/loyal_customers_input_2025-12-26.txt
new file mode 100644
index 0000000..156450c
--- /dev/null
+++ b/etl_billiards/reports/loyal_customers_input_2025-12-26.txt
@@ -0,0 +1,72 @@
+黄生 13609719719
+曾巧明 18688471488
+葛先生 13811638071
+孟紫龙 17631643741
+桂先生 16676777275
+孟紫龙(该会员已注销) 17631643741(1)
+陈先生 13922200419
+候 13161960323
+小燕 17802081334
+陈先生 15915782829
+牛先生 15201265159
+李先生 13427574343
+汪先生 13925126339
+林先生 13342871070
+桂先生(该会员已注销) 16676777275(1)
+贺斌 15017500885
+谢俊 18620395198
+郑先生 15902794331
+周先生 19350986822
+王先生 18520321125
+胡先生 18620043391
+罗先生 13924036996
+刘女士 17727637538
+魏先生 13726266862
+吴生 13600453341
+王先生 18302299763
+梅 13672464552
+郭先生 15622365001
+艾宇民 15062279958
+阿亮 15920462628
+林先生 13763388785
+李先生 13128264000
+陈腾鑫 17817318218
+昌哥 13798811229
+张先生 13902258852
+黄先生 13570163507
+陈德韩 13431017864
+罗先生 13922289222
+陈世 13430271938
+T 18028579962
+大G 18680114598
+卢广贤 18613066220
+叶总 13711223287
+杜先生 18826454705
+谭先生 13824473185
+杨 13066365960
+小熊 13927020145
+曾先生 13316091235
+游 17267866666
+夏 19120942851
+胡总 13385143091
+轩哥 18826267530
+常总 18570077188
+歌神 18819262164
+君姐 16624614594
+叶先生 13826479539
+江先生 18819484838
+黄先生 15818822109
+张先生 13682854528
+陶 18924022151
+林总 13808881180
+林先生 18826220332
+李 13189179882
+张丹逸 13609066637
+罗超杰 13711268012
+小宇 18745728077
+蔡总 15914338893
+羊 18785445094
+林志铭 13570304233
+钟智豪 18814002803
+明哥 16620040999
+冯先生 15588690348
diff --git a/etl_billiards/reports/loyal_customers_total_hours_for_list.py b/etl_billiards/reports/loyal_customers_total_hours_for_list.py
new file mode 100644
index 0000000..41abbac
--- /dev/null
+++ b/etl_billiards/reports/loyal_customers_total_hours_for_list.py
@@ -0,0 +1,384 @@
+# -*- coding: utf-8 -*-
+"""
+按自定义名单统计累计打球总时长(同“忠实台球类竞技客户”口径)
+
+默认口径:
+- 时间范围:2025-10-01 至今天(可传参覆盖)
+- 仅统计 member_id != 0 且有时长的记录
+- 台桌区域过滤:A区/B区/C区/VIP包厢/斯诺克区/TV台(可传参覆盖)
+- 同一客户同一天同时开多台:按时间区间并集计时(避免重复叠加)
+
+输入:每行 “姓名联系方式”
+输出:CSV(UTF-8-SIG,便于 Excel 打开)
+
+运行方式(需在 etl_billiards/ 下以模块方式运行):
+ python -m reports.loyal_customers_total_hours_for_list --input reports/loyal_customers_input_2025-12-26.txt
+"""
+
+from __future__ import annotations
+
+import argparse
+import csv
+import re
+from dataclasses import dataclass
+from datetime import datetime, time, timedelta
+from pathlib import Path
+from zoneinfo import ZoneInfo
+
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+from reports.loyal_billiards_customers_report import DEFAULT_AREAS, SessionRow, _as_tz, _build_member_aggs, _parse_date
+
+
+@dataclass(frozen=True)
+class InputRow:
+ idx: int
+ name: str
+ phone_raw: str
+ phone_digits: str
+
+
+def _digits(s: str) -> str:
+ return re.sub(r"\D+", "", s or "")
+
+
+def _normalize_name(s: str) -> str:
+ s = (s or "").strip()
+ s = re.sub(r"[((].*?[))]", "", s)
+ s = re.sub(r"\s+", "", s)
+ return s
+
+
+def _read_input(path: Path) -> list[InputRow]:
+ rows: list[InputRow] = []
+ with path.open("r", encoding="utf-8") as f:
+ for i, line in enumerate(f, start=1):
+ line = (line or "").strip()
+ if not line or line.startswith("#"):
+ continue
+ parts = re.split(r"\t+", line)
+ if len(parts) < 2:
+ parts = re.split(r"\s+", line)
+ if len(parts) < 2:
+ continue
+ name = parts[0].strip()
+ phone_raw = parts[1].strip()
+ rows.append(InputRow(idx=i, name=name, phone_raw=phone_raw, phone_digits=_digits(phone_raw)))
+ return rows
+
+
+def _load_member_candidates_by_phone(
+ conn: DatabaseConnection,
+ *,
+ store_id: int,
+ phone_digits_list: list[str],
+) -> dict[str, dict[int, str]]:
+ if not phone_digits_list:
+ return {}
+ sql = """
+ SELECT DISTINCT
+ member_id,
+ member_name,
+ member_phone
+ FROM billiards_dwd.dwd_settlement_head
+ WHERE site_id = %s
+ AND member_id IS NOT NULL
+ AND member_id <> 0
+ AND regexp_replace(COALESCE(member_phone, ''), '\\D', '', 'g') = ANY(%s)
+ """
+ rows = conn.query(sql, (store_id, phone_digits_list))
+ out: dict[str, dict[int, str]] = {}
+ for r in rows:
+ mid = int(r.get("member_id") or 0)
+ if mid <= 0:
+ continue
+ phone_digits = _digits(r.get("member_phone") or "")
+ if not phone_digits:
+ continue
+ name = str(r.get("member_name") or "")
+ out.setdefault(phone_digits, {})
+ if mid not in out[phone_digits]:
+ out[phone_digits][mid] = name
+ return out
+
+
+def _load_member_candidates_by_mobile(
+ conn: DatabaseConnection,
+ *,
+ phone_digits_list: list[str],
+) -> dict[str, dict[int, str]]:
+ if not phone_digits_list:
+ return {}
+ sql = """
+ SELECT member_id, nickname, mobile
+ FROM billiards_dwd.dim_member
+ WHERE scd2_is_current = 1
+ AND member_id IS NOT NULL
+ AND member_id <> 0
+ AND regexp_replace(COALESCE(mobile, ''), '\\D', '', 'g') = ANY(%s)
+ """
+ rows = conn.query(sql, (phone_digits_list,))
+ out: dict[str, dict[int, str]] = {}
+ for r in rows:
+ mid = int(r.get("member_id") or 0)
+ if mid <= 0:
+ continue
+ phone_digits = _digits(r.get("mobile") or "")
+ if not phone_digits:
+ continue
+ name = str(r.get("nickname") or "")
+ out.setdefault(phone_digits, {})
+ if mid not in out[phone_digits]:
+ out[phone_digits][mid] = name
+ return out
+
+
+def _resolve_member_ids(
+ row: InputRow,
+ *,
+ settle_candidates: dict[str, dict[int, str]],
+ dim_candidates: dict[str, dict[int, str]],
+) -> list[int]:
+ phone_digits = row.phone_digits
+ candidate_map: dict[int, list[str]] = {}
+
+ for mid, name in (settle_candidates.get(phone_digits) or {}).items():
+ candidate_map.setdefault(int(mid), []).append(str(name or ""))
+ for mid, name in (dim_candidates.get(phone_digits) or {}).items():
+ candidate_map.setdefault(int(mid), []).append(str(name or ""))
+
+ candidate_ids = sorted(candidate_map.keys())
+ if len(candidate_ids) <= 1:
+ return candidate_ids
+
+ name_clean = _normalize_name(row.name)
+ if not name_clean:
+ return candidate_ids
+
+ filtered: list[int] = []
+ for mid in candidate_ids:
+ names = candidate_map.get(mid) or []
+ if any(name_clean in _normalize_name(n) or _normalize_name(n) in name_clean for n in names if n):
+ filtered.append(mid)
+ return filtered or candidate_ids
+
+
+def _load_sessions_for_members(
+ conn: DatabaseConnection,
+ *,
+ store_id: int,
+ tz: ZoneInfo,
+ start_dt: datetime,
+ end_dt: datetime,
+ areas: tuple[str, ...],
+ member_ids: list[int],
+) -> list[SessionRow]:
+ if not member_ids:
+ return []
+ sql = """
+ SELECT
+ member_id,
+ start_use_time,
+ ledger_end_time,
+ real_table_use_seconds,
+ site_table_area_name
+ FROM billiards_dwd.dwd_table_fee_log
+ WHERE site_id = %s
+ AND member_id = ANY(%s)
+ AND start_use_time >= %s
+ AND start_use_time < %s
+ AND site_table_area_name = ANY(%s)
+ """
+ rows = conn.query(sql, (store_id, member_ids, start_dt, end_dt, list(areas)))
+ sessions: list[SessionRow] = []
+ for r in rows:
+ mid = int(r.get("member_id") or 0)
+ if mid <= 0:
+ continue
+ start = r.get("start_use_time")
+ end = r.get("ledger_end_time")
+ if not isinstance(start, datetime):
+ continue
+ if isinstance(end, datetime):
+ pass
+ else:
+ secs = r.get("real_table_use_seconds")
+ try:
+ secs = int(secs or 0)
+ except Exception:
+ secs = 0
+ if secs > 0:
+ end = start + timedelta(seconds=secs)
+ else:
+ continue
+
+ start = _as_tz(start, tz)
+ end = _as_tz(end, tz)
+ if end <= start:
+ continue
+
+ sessions.append(SessionRow(member_id=mid, start=start, end=end, area_name=r.get("site_table_area_name")))
+ return sessions
+
+
+def _write_report(out_path: Path, *, tz: ZoneInfo, rows: list[dict]):
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ with out_path.open("w", encoding="utf-8-sig", newline="") as f:
+ w = csv.writer(f)
+ w.writerow(
+ [
+ "排名",
+ "客户姓名",
+ "联系方式",
+ "10-12月打球总时长(小时)",
+ "来店日数",
+ "最后一次到店日期",
+ "匹配member_id列表",
+ "匹配状态",
+ ]
+ )
+ for r in rows:
+ last_visit = r.get("last_visit_at")
+ last_visit_str = ""
+ if isinstance(last_visit, datetime):
+ last_visit_str = _as_tz(last_visit, tz).strftime("%Y-%m-%d %H:%M")
+ w.writerow(
+ [
+ r.get("rank", ""),
+ r.get("name", ""),
+ r.get("phone_raw", ""),
+ f"{float(r.get('total_hours') or 0.0):.2f}",
+ int(r.get("visit_days") or 0),
+ last_visit_str,
+ r.get("member_ids_str", ""),
+ r.get("status", ""),
+ ]
+ )
+
+
+def main() -> int:
+ parser = argparse.ArgumentParser(description="Total play hours for a custom customer list")
+ parser.add_argument("--input", default=str(Path(__file__).with_name("loyal_customers_input_2025-12-26.txt")))
+ parser.add_argument("--start-date", default="2025-10-01", help="YYYY-MM-DD")
+ parser.add_argument("--end-date", default="", help="YYYY-MM-DD (default: today)")
+ parser.add_argument("--areas", default=",".join(DEFAULT_AREAS), help="comma separated")
+ parser.add_argument("--out", default="", help="output csv path")
+ args = parser.parse_args()
+
+ cfg = AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ store_id = int(cfg.get("app.store_id"))
+
+ input_path = Path(args.input)
+ if not input_path.is_file():
+ raise SystemExit(f"input not found: {input_path}")
+
+ start_date = _parse_date(args.start_date)
+ end_date = _parse_date(args.end_date) if args.end_date else datetime.now(tz).date()
+ if end_date < start_date:
+ raise SystemExit("end_date must be >= start_date")
+
+ start_dt = datetime.combine(start_date, time.min).replace(tzinfo=tz)
+ end_dt = datetime.combine(end_date + timedelta(days=1), time.min).replace(tzinfo=tz)
+
+ areas = tuple([a.strip() for a in str(args.areas or "").split(",") if a.strip()])
+ if not areas:
+ raise SystemExit("areas is empty")
+
+ input_rows = _read_input(input_path)
+ phone_digits_list = sorted({r.phone_digits for r in input_rows if r.phone_digits})
+
+ conn = DatabaseConnection(dsn=cfg["db"]["dsn"], session=cfg["db"].get("session"))
+ try:
+ settle_candidates = _load_member_candidates_by_phone(conn, store_id=store_id, phone_digits_list=phone_digits_list)
+ dim_candidates = _load_member_candidates_by_mobile(conn, phone_digits_list=phone_digits_list)
+
+ per_input_member_ids: dict[int, list[int]] = {}
+ all_member_ids: set[int] = set()
+ for r in input_rows:
+ mids = _resolve_member_ids(r, settle_candidates=settle_candidates, dim_candidates=dim_candidates)
+ per_input_member_ids[r.idx] = mids
+ all_member_ids.update(mids)
+
+ sessions = _load_sessions_for_members(
+ conn,
+ store_id=store_id,
+ tz=tz,
+ start_dt=start_dt,
+ end_dt=end_dt,
+ areas=areas,
+ member_ids=sorted(all_member_ids),
+ )
+ finally:
+ conn.close()
+
+ aggs = _build_member_aggs(sessions, tz)
+ agg_by_member = {int(a.member_id): a for a in aggs}
+
+ out_rows: list[dict] = []
+ for r in input_rows:
+ mids = per_input_member_ids.get(r.idx) or []
+ if not mids:
+ out_rows.append(
+ {
+ "rank": "",
+ "name": r.name,
+ "phone_raw": r.phone_raw,
+ "total_hours": 0.0,
+ "visit_days": 0,
+ "last_visit_at": None,
+ "member_ids_str": "",
+ "status": "NOT_FOUND",
+ }
+ )
+ continue
+
+ total_hours = 0.0
+ visit_days = 0
+ last_visit_at = None
+ found_any = False
+ for mid in mids:
+ agg = agg_by_member.get(int(mid))
+ if not agg:
+ continue
+ found_any = True
+ total_hours += float(agg.total_hours or 0.0)
+ visit_days += int(agg.visit_days or 0)
+ if isinstance(agg.last_visit_at, datetime):
+ if last_visit_at is None or agg.last_visit_at > last_visit_at:
+ last_visit_at = agg.last_visit_at
+
+ status = "OK"
+ if len(mids) > 1:
+ status = "MULTI_MEMBER_ID"
+ if not found_any:
+ status = "NO_SESSIONS"
+
+ out_rows.append(
+ {
+ "rank": "",
+ "name": r.name,
+ "phone_raw": r.phone_raw,
+ "total_hours": total_hours,
+ "visit_days": visit_days,
+ "last_visit_at": last_visit_at,
+ "member_ids_str": ",".join([str(x) for x in mids]),
+ "status": status,
+ }
+ )
+
+ out_rows_sorted = sorted(out_rows, key=lambda x: float(x.get("total_hours") or 0.0), reverse=True)
+ for i, r in enumerate(out_rows_sorted, start=1):
+ r["rank"] = i
+
+ today = datetime.now(tz).date().isoformat()
+ base_dir = Path(args.out).parent if args.out else Path(__file__).parent
+ out_path = Path(args.out) if args.out else base_dir / f"loyal_customers_total_hours_for_list_{today}.csv"
+ _write_report(out_path, tz=tz, rows=out_rows_sorted)
+ print(str(out_path))
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
+
diff --git a/etl_billiards/reports/loyal_customers_total_hours_for_list_2025-12-26.csv b/etl_billiards/reports/loyal_customers_total_hours_for_list_2025-12-26.csv
new file mode 100644
index 0000000..d7d14fe
--- /dev/null
+++ b/etl_billiards/reports/loyal_customers_total_hours_for_list_2025-12-26.csv
@@ -0,0 +1,73 @@
+排名,客户姓名,联系方式,10-12月打球总时长(小时),来店日数,最后一次到店日期,匹配member_id列表,匹配状态
+1,曾巧明,18688471488,443.80,71,2025-12-25 15:49,2799207403554565,OK
+2,黄生,13609719719,323.64,43,2025-12-24 14:51,2799207390349061,OK
+3,葛先生,13811638071,226.56,39,2025-12-26 00:55,2799207363643141,OK
+4,罗先生,13924036996,185.01,65,2025-12-25 22:25,2799207359858437,OK
+5,谢俊,18620395198,163.86,53,2025-12-22 20:03,2799207352715013,OK
+6,桂先生,16676777275,117.52,25,2025-12-16 19:05,2933647801731013,OK
+7,陈腾鑫,17817318218,117.32,50,2025-12-12 21:39,2799207124305669,OK
+8,艾宇民,15062279958,112.83,47,2025-12-25 20:28,2799207328155397,OK
+9,小燕,17802081334,103.72,29,2025-12-22 20:10,2969257129938053,OK
+10,张先生,13902258852,94.55,43,2025-12-24 18:42,2799207406946053,OK
+11,孟紫龙,17631643741,80.36,17,2025-12-23 16:27,2985941423934469,OK
+12,黄先生,13570163507,48.36,22,2025-12-24 15:58,2799212430657285,OK
+13,李先生,13427574343,47.40,14,2025-12-24 22:49,2970668087594181,OK
+14,轩哥,18826267530,46.27,25,2025-12-18 02:11,2799207522600709,OK
+15,吴生,13600453341,36.47,14,2025-12-25 17:51,2799207356434181,OK
+16,郑先生,15902794331,36.14,12,2025-12-10 22:12,2976361970370373,OK
+17,周先生,19350986822,32.16,11,2025-12-26 02:06,2995832745758917,OK
+18,孟紫龙(该会员已注销),17631643741(1),27.85,6,2025-10-13 18:57,"2799212728911621,2878376367018757",MULTI_MEMBER_ID
+19,江先生,18819484838,22.87,15,2025-12-13 19:24,2820625955784965,OK
+20,候,13161960323,22.01,6,2025-12-17 23:13,3003552553390789,OK
+21,T,18028579962,19.25,9,2025-12-18 17:36,2935271033079557,OK
+22,桂先生(该会员已注销),16676777275(1),19.03,6,2025-10-16 19:37,2881216340641797,OK
+23,蔡总,15914338893,17.18,17,2025-12-24 00:30,2799212491392773,OK
+24,阿亮,15920462628,16.79,7,2025-12-04 20:05,2976376546117574,OK
+25,叶先生,13826479539,15.95,10,2025-12-05 23:07,2799207342704389,OK
+26,曾先生,13316091235,15.33,8,2025-12-24 11:53,2799210181019397,OK
+27,游,17267866666,15.10,8,2025-12-07 17:36,2799207435323141,OK
+28,叶总,13711223287,14.55,7,2025-10-27 20:57,2844990190242821,OK
+29,林先生,13763388785,14.34,6,2025-12-02 19:48,2799207067109125,OK
+30,陈德韩,13431017864,13.08,6,2025-10-26 19:59,2799209806071557,OK
+31,罗先生,13922289222,12.94,6,2025-11-26 18:54,2799209768765189,OK
+32,李先生,13128264000,11.81,5,2025-11-07 23:01,2799207545685765,OK
+33,胡先生,18620043391,11.56,4,2025-12-01 19:01,2955204541320325,OK
+34,夏,19120942851,11.30,6,2025-11-06 18:05,2799207519176453,OK
+35,卢广贤,18613066220,10.41,5,2025-12-13 15:27,2799207163447045,OK
+36,黄先生,15818822109,10.39,7,2025-12-17 00:58,2846153189592005,OK
+37,牛先生,15201265159,10.33,3,2025-11-24 17:10,2973479575832453,OK
+38,贺斌,15017500885,9.45,3,2025-11-03 18:42,2938229628340421,OK
+39,羊,18785445094,8.91,9,2025-11-23 19:27,2799207378798341,OK
+40,陶,18924022151,8.47,6,2025-10-26 23:52,2919518015802181,OK
+41,李,13189179882,7.98,6,2025-11-24 12:38,2860039721438277,OK
+42,罗超杰,13711268012,7.45,7,2025-11-05 15:50,2799207338198789,OK
+43,郭先生,15622365001,7.29,3,2025-11-01 20:06,2847747357002757,OK
+44,汪先生,13925126339,6.69,2,2025-10-08 20:59,2799207287523077,OK
+45,陈世,13430271938,6.45,3,2025-11-20 21:45,2799207229441797,OK
+46,王先生,18520321125,5.82,2,2025-12-02 21:00,2970386005050949,OK
+47,小熊,13927020145,5.82,3,2025-11-04 17:36,2799207599212293,OK
+48,林总,13808881180,5.61,4,2025-12-24 19:18,2799207256426245,OK
+49,常总,18570077188,5.52,3,2025-12-22 19:21,3003185854190085,OK
+50,林先生,18826220332,5.46,4,2025-12-24 00:28,2946070922169029,OK
+51,魏先生,13726266862,5.39,2,2025-12-05 22:18,2799209794651909,OK
+52,歌神,18819262164,5.25,3,2025-10-24 21:47,2799207370163973,OK
+53,昌哥,13798811229,4.54,2,2025-12-07 21:05,2974770547348357,OK
+54,大G,18680114598,4.20,2,2025-12-02 20:53,2799207533332229,OK
+55,杨,13066365960,4.00,2,2025-12-05 19:28,2799212333647621,OK
+56,陈先生,13922200419,3.92,1,2025-10-18 12:35,2799210049521413,OK
+57,胡总,13385143091,3.72,2,2025-12-20 21:00,2799209753708293,OK
+58,陈先生,15915782829,3.48,1,2025-11-07 00:44,2799207290996485,OK
+59,君姐,16624614594,3.32,2,2025-11-27 21:22,2983452013021509,OK
+60,林先生,13342871070,3.30,1,2025-12-05 15:52,2976465665476741,OK
+61,张先生,13682854528,2.96,2,2025-12-19 22:37,2963357031615941,OK
+62,刘女士,17727637538,2.80,1,2025-10-14 18:24,2853881398644101,OK
+63,王先生,18302299763,2.58,1,2025-12-24 18:30,2973199975761797,OK
+64,梅,13672464552,2.47,1,2025-11-22 20:29,2975065345119045,OK
+65,张丹逸,13609066637,2.40,2,2025-10-06 22:47,2799207176636165,OK
+66,小宇,18745728077,2.06,2,2025-10-13 16:24,2799212906235653,OK
+67,杜先生,18826454705,2.03,1,2025-11-02 20:12,2799209786836741,OK
+68,谭先生,13824473185,2.03,1,2025-10-20 17:15,2929237914683013,OK
+69,明哥,16620040999,1.99,3,2025-12-09 22:42,2799210064873221,OK
+70,林志铭,13570304233,1.96,2,2025-11-30 16:19,2799207188170501,OK
+71,钟智豪,18814002803,1.76,2,2025-11-28 23:50,2938228399917253,OK
+72,冯先生,15588690348,0.93,2,2025-10-31 23:34,2799212808029957,OK
diff --git a/etl_billiards/reports/ods_gap_check_20260115_073006.json b/etl_billiards/reports/ods_gap_check_20260115_073006.json
new file mode 100644
index 0000000..ead4710
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_073006.json
@@ -0,0 +1,385 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T07:28:43.859529+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 64,
+ "records_with_pk": 64,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.assistant_accounts_master t J...\n ^\n"
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 16,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.settlement_records t JOIN (VA...\n ^\n"
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.table_fee_transactions t JOIN...\n ^\n"
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.assistant_service_records t J...\n ^\n"
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 106,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.assistant_cancellation_record...\n ^\n"
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.payment_transactions t JOIN (...\n ^\n"
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.refund_transactions t JOIN (V...\n ^\n"
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.platform_coupon_redemption_re...\n ^\n"
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.member_profiles t JOIN (VALUE...\n ^\n"
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.member_stored_value_cards t J...\n ^\n"
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.member_balance_changes t JOIN...\n ^\n"
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 21,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.recharge_settlements t JOIN (...\n ^\n"
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.group_buy_packages t JOIN (VA...\n ^\n"
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.group_buy_redemption_records ...\n ^\n"
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"sitegoodsid\" 是不明确的\nLINE 1: SELECT \"sitegoodsid\" FROM billiards_ods.goods_stock_summary ...\n ^\n"
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 62,
+ "records_with_pk": 62,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 18,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"sitegoodsstockid\" 是不明确的\nLINE 1: SELECT \"sitegoodsstockid\" FROM billiards_ods.goods_stock_mov...\n ^\n"
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.site_tables_master t JOIN (VA...\n ^\n"
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.stock_goods_category_tree t J...\n ^\n"
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.store_goods_master t JOIN (VA...\n ^\n"
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 200,
+ "records_with_pk": 200,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.table_fee_discount_records t ...\n ^\n"
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "AmbiguousColumn: 错误: 字段关联 \"id\" 是不明确的\nLINE 1: SELECT \"id\" FROM billiards_ods.tenant_goods_master t JOIN (V...\n ^\n"
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22265,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 203,
+ "skipped_missing_pk": 22265,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 21,
+ "generated_at": "2026-01-15T07:30:06.858721+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_073926.json b/etl_billiards/reports/ods_gap_check_20260115_073926.json
new file mode 100644
index 0000000..5a89acc
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_073926.json
@@ -0,0 +1,838 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T07:30:39.379740+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12736,
+ "records_with_pk": 12736,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21625,
+ "records_with_pk": 21625,
+ "missing": 5554,
+ "missing_samples": [
+ {
+ "id": 2793005672007237
+ },
+ {
+ "id": 2794775029944453
+ },
+ {
+ "id": 2794723221669957
+ },
+ {
+ "id": 2795846081054981
+ },
+ {
+ "id": 2797459120852869
+ },
+ {
+ "id": 2797370356928517
+ },
+ {
+ "id": 2797170093527045
+ },
+ {
+ "id": 2797169961897989
+ },
+ {
+ "id": 2798802248288261
+ },
+ {
+ "id": 2798636101421317
+ },
+ {
+ "id": 2800804425353349
+ },
+ {
+ "id": 2800797279504261
+ },
+ {
+ "id": 2800796097267589
+ },
+ {
+ "id": 2800795223918661
+ },
+ {
+ "id": 2800792829986693
+ },
+ {
+ "id": 2800791828547461
+ },
+ {
+ "id": 2800790859499397
+ },
+ {
+ "id": 2800779801462661
+ },
+ {
+ "id": 2800779692902277
+ },
+ {
+ "id": 2800771371960389
+ },
+ {
+ "id": 2800770730772485
+ },
+ {
+ "id": 2800770224490629
+ },
+ {
+ "id": 2800765767043077
+ },
+ {
+ "id": 2800753238165381
+ },
+ {
+ "id": 2800745545254789
+ },
+ {
+ "id": 2800734778001413
+ },
+ {
+ "id": 2800719579875205
+ },
+ {
+ "id": 2800714836166661
+ },
+ {
+ "id": 2800714753411013
+ },
+ {
+ "id": 2800712176470085
+ },
+ {
+ "id": 2800711353370501
+ },
+ {
+ "id": 2800706200422341
+ },
+ {
+ "id": 2800702845536197
+ },
+ {
+ "id": 2800701729900485
+ },
+ {
+ "id": 2800700704409605
+ },
+ {
+ "id": 2800698665420741
+ },
+ {
+ "id": 2800693776926661
+ },
+ {
+ "id": 2800678221105093
+ },
+ {
+ "id": 2800677073487813
+ },
+ {
+ "id": 2800675629844549
+ },
+ {
+ "id": 2800675308767109
+ },
+ {
+ "id": 2800659322996613
+ },
+ {
+ "id": 2800653584042053
+ },
+ {
+ "id": 2800653414778821
+ },
+ {
+ "id": 2800651389634630
+ },
+ {
+ "id": 2800643230435205
+ },
+ {
+ "id": 2800637690595269
+ },
+ {
+ "id": 2800630547269509
+ },
+ {
+ "id": 2800620726110149
+ },
+ {
+ "id": 2800619316873221
+ }
+ ],
+ "pages": 202,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9827,
+ "records_with_pk": 9827,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4431,
+ "records_with_pk": 4431,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11847,
+ "records_with_pk": 11847,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 37,
+ "records_with_pk": 37,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16006,
+ "records_with_pk": 16006,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2432,
+ "records_with_pk": 2432,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 122,
+ "missing_samples": [
+ {
+ "id": 2800763348731909
+ },
+ {
+ "id": 2802064357345349
+ },
+ {
+ "id": 2801879399532933
+ },
+ {
+ "id": 2800824057628741
+ },
+ {
+ "id": 2803649174965445
+ },
+ {
+ "id": 2803524215835845
+ },
+ {
+ "id": 2802480974171333
+ },
+ {
+ "id": 2802393839258885
+ },
+ {
+ "id": 2802362619840581
+ },
+ {
+ "id": 2804767340973317
+ },
+ {
+ "id": 2803710575593541
+ },
+ {
+ "id": 2803666932010565
+ },
+ {
+ "id": 2803661545508421
+ },
+ {
+ "id": 2806426635208517
+ },
+ {
+ "id": 2806371278325381
+ },
+ {
+ "id": 2806244951017285
+ },
+ {
+ "id": 2805188835477573
+ },
+ {
+ "id": 2805121951074373
+ },
+ {
+ "id": 2805111552117957
+ },
+ {
+ "id": 2805070136823365
+ },
+ {
+ "id": 2807891556897349
+ },
+ {
+ "id": 2807815241847557
+ },
+ {
+ "id": 2806859908384389
+ },
+ {
+ "id": 2806855233947525
+ },
+ {
+ "id": 2806708031637381
+ },
+ {
+ "id": 2809187656829061
+ },
+ {
+ "id": 2808923174783109
+ },
+ {
+ "id": 2807912803045957
+ },
+ {
+ "id": 2807909672309637
+ },
+ {
+ "id": 2810563362048453
+ },
+ {
+ "id": 2810546930207237
+ },
+ {
+ "id": 2810412839373574
+ },
+ {
+ "id": 2810371281799621
+ },
+ {
+ "id": 2809504839059909
+ },
+ {
+ "id": 2809471788321221
+ },
+ {
+ "id": 2809392429549765
+ },
+ {
+ "id": 2811829130856901
+ },
+ {
+ "id": 2810801124133381
+ },
+ {
+ "id": 2810800364193989
+ },
+ {
+ "id": 2812352420645317
+ },
+ {
+ "id": 2812164953934597
+ },
+ {
+ "id": 2812160863095557
+ },
+ {
+ "id": 2814476335547909
+ },
+ {
+ "id": 2813729032046789
+ },
+ {
+ "id": 2816375660284933
+ },
+ {
+ "id": 2816013068586693
+ },
+ {
+ "id": 2815107864956613
+ },
+ {
+ "id": 2817594853805701
+ },
+ {
+ "id": 2816455124847557
+ },
+ {
+ "id": 2819131204669189
+ }
+ ],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8218,
+ "records_with_pk": 8218,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28417,
+ "records_with_pk": 28417,
+ "missing": 128,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 2796087732473349
+ },
+ {
+ "sitegoodsstockid": 2796087732375045
+ },
+ {
+ "sitegoodsstockid": 2796085792214469
+ },
+ {
+ "sitegoodsstockid": 2796085791641029
+ },
+ {
+ "sitegoodsstockid": 2796085792116165
+ },
+ {
+ "sitegoodsstockid": 2796085791542725
+ },
+ {
+ "sitegoodsstockid": 2796082589486533
+ },
+ {
+ "sitegoodsstockid": 2796082589027781
+ },
+ {
+ "sitegoodsstockid": 2796082588552645
+ },
+ {
+ "sitegoodsstockid": 2796082587995589
+ },
+ {
+ "sitegoodsstockid": 2796082587520453
+ },
+ {
+ "sitegoodsstockid": 2796082587028933
+ },
+ {
+ "sitegoodsstockid": 2796082586570181
+ },
+ {
+ "sitegoodsstockid": 2796082586013125
+ },
+ {
+ "sitegoodsstockid": 2796082585505221
+ },
+ {
+ "sitegoodsstockid": 2796082589584837
+ },
+ {
+ "sitegoodsstockid": 2796082589126085
+ },
+ {
+ "sitegoodsstockid": 2796082588650949
+ },
+ {
+ "sitegoodsstockid": 2796082588110277
+ },
+ {
+ "sitegoodsstockid": 2796082587618757
+ },
+ {
+ "sitegoodsstockid": 2796082587127237
+ },
+ {
+ "sitegoodsstockid": 2796082586668485
+ },
+ {
+ "sitegoodsstockid": 2796082586111429
+ },
+ {
+ "sitegoodsstockid": 2796082585603525
+ },
+ {
+ "sitegoodsstockid": 2796082584784325
+ },
+ {
+ "sitegoodsstockid": 2796082584292805
+ },
+ {
+ "sitegoodsstockid": 2796082583768517
+ },
+ {
+ "sitegoodsstockid": 2796082583260613
+ },
+ {
+ "sitegoodsstockid": 2796082582752709
+ },
+ {
+ "sitegoodsstockid": 2796082584686021
+ },
+ {
+ "sitegoodsstockid": 2796082584194501
+ },
+ {
+ "sitegoodsstockid": 2796082583653829
+ },
+ {
+ "sitegoodsstockid": 2796082583162309
+ },
+ {
+ "sitegoodsstockid": 2796082582654405
+ },
+ {
+ "sitegoodsstockid": 2796074872851973
+ },
+ {
+ "sitegoodsstockid": 2796074872753669
+ },
+ {
+ "sitegoodsstockid": 2796074436742661
+ },
+ {
+ "sitegoodsstockid": 2796074436578821
+ },
+ {
+ "sitegoodsstockid": 2796074059976133
+ },
+ {
+ "sitegoodsstockid": 2796074059894213
+ },
+ {
+ "sitegoodsstockid": 2796073653128709
+ },
+ {
+ "sitegoodsstockid": 2796073653030405
+ },
+ {
+ "sitegoodsstockid": 2796073284095429
+ },
+ {
+ "sitegoodsstockid": 2796073283997125
+ },
+ {
+ "sitegoodsstockid": 2796072902577605
+ },
+ {
+ "sitegoodsstockid": 2796072902675909
+ },
+ {
+ "sitegoodsstockid": 2796072030784965
+ },
+ {
+ "sitegoodsstockid": 2796072030703045
+ },
+ {
+ "sitegoodsstockid": 2796070969183685
+ },
+ {
+ "sitegoodsstockid": 2796070969298373
+ }
+ ],
+ "pages": 238,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1649,
+ "records_with_pk": 1649,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22265,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 203,
+ "skipped_missing_pk": 22265,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5804,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T07:39:26.592004+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_103858.json b/etl_billiards/reports/ods_gap_check_20260115_103858.json
new file mode 100644
index 0000000..d800600
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_103858.json
@@ -0,0 +1,854 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T09:48:49.829033+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 50816,
+ "records_with_pk": 50816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21513,
+ "records_with_pk": 21513,
+ "missing": 5554,
+ "missing_samples": [
+ {
+ "id": 2793005672007237
+ },
+ {
+ "id": 2794775029944453
+ },
+ {
+ "id": 2794723221669957
+ },
+ {
+ "id": 2795846081054981
+ },
+ {
+ "id": 2797170093527045
+ },
+ {
+ "id": 2797169961897989
+ },
+ {
+ "id": 2797459120852869
+ },
+ {
+ "id": 2797370356928517
+ },
+ {
+ "id": 2798636101421317
+ },
+ {
+ "id": 2798802248288261
+ },
+ {
+ "id": 2800105539552709
+ },
+ {
+ "id": 2800050273584581
+ },
+ {
+ "id": 2800462764542021
+ },
+ {
+ "id": 2800460224120773
+ },
+ {
+ "id": 2800454900648005
+ },
+ {
+ "id": 2800448023513157
+ },
+ {
+ "id": 2800442606962629
+ },
+ {
+ "id": 2800433643243525
+ },
+ {
+ "id": 2800430651182085
+ },
+ {
+ "id": 2800428852725765
+ },
+ {
+ "id": 2800423540131717
+ },
+ {
+ "id": 2800421742806917
+ },
+ {
+ "id": 2800420036233221
+ },
+ {
+ "id": 2800410925254597
+ },
+ {
+ "id": 2800410227705733
+ },
+ {
+ "id": 2800392593475653
+ },
+ {
+ "id": 2800388746184581
+ },
+ {
+ "id": 2800388462479301
+ },
+ {
+ "id": 2800383220615109
+ },
+ {
+ "id": 2800379828701189
+ },
+ {
+ "id": 2800379750893445
+ },
+ {
+ "id": 2800379609925573
+ },
+ {
+ "id": 2800378758907845
+ },
+ {
+ "id": 2800378535118789
+ },
+ {
+ "id": 2800371960039365
+ },
+ {
+ "id": 2800363039770693
+ },
+ {
+ "id": 2800360608303045
+ },
+ {
+ "id": 2800353168738309
+ },
+ {
+ "id": 2800353054263173
+ },
+ {
+ "id": 2800348877604741
+ },
+ {
+ "id": 2800348098742341
+ },
+ {
+ "id": 2800343364913157
+ },
+ {
+ "id": 2800328443021317
+ },
+ {
+ "id": 2800320895223685
+ },
+ {
+ "id": 2800316938717189
+ },
+ {
+ "id": 2800311915366341
+ },
+ {
+ "id": 2800301266225093
+ },
+ {
+ "id": 2800272176744389
+ },
+ {
+ "id": 2800265338046277
+ },
+ {
+ "id": 2800262033213317
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9751,
+ "records_with_pk": 9751,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815030085
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4415,
+ "records_with_pk": 4415,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 78,
+ "records_with_pk": 78,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11733,
+ "records_with_pk": 11733,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863811867973
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16006,
+ "records_with_pk": 16006,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2407,
+ "records_with_pk": 2407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 122,
+ "missing_samples": [
+ {
+ "id": 2800763348731909
+ },
+ {
+ "id": 2800824057628741
+ },
+ {
+ "id": 2801879399532933
+ },
+ {
+ "id": 2802064357345349
+ },
+ {
+ "id": 2802480974171333
+ },
+ {
+ "id": 2802393839258885
+ },
+ {
+ "id": 2802362619840581
+ },
+ {
+ "id": 2803649174965445
+ },
+ {
+ "id": 2803524215835845
+ },
+ {
+ "id": 2803710575593541
+ },
+ {
+ "id": 2803666932010565
+ },
+ {
+ "id": 2803661545508421
+ },
+ {
+ "id": 2804767340973317
+ },
+ {
+ "id": 2805188835477573
+ },
+ {
+ "id": 2805121951074373
+ },
+ {
+ "id": 2805111552117957
+ },
+ {
+ "id": 2805070136823365
+ },
+ {
+ "id": 2806426635208517
+ },
+ {
+ "id": 2806371278325381
+ },
+ {
+ "id": 2806244951017285
+ },
+ {
+ "id": 2806708031637381
+ },
+ {
+ "id": 2806859908384389
+ },
+ {
+ "id": 2806855233947525
+ },
+ {
+ "id": 2807891556897349
+ },
+ {
+ "id": 2807815241847557
+ },
+ {
+ "id": 2807912803045957
+ },
+ {
+ "id": 2807909672309637
+ },
+ {
+ "id": 2808923174783109
+ },
+ {
+ "id": 2809187656829061
+ },
+ {
+ "id": 2809504839059909
+ },
+ {
+ "id": 2809471788321221
+ },
+ {
+ "id": 2809392429549765
+ },
+ {
+ "id": 2810371281799621
+ },
+ {
+ "id": 2810563362048453
+ },
+ {
+ "id": 2810546930207237
+ },
+ {
+ "id": 2810412839373574
+ },
+ {
+ "id": 2810801124133381
+ },
+ {
+ "id": 2810800364193989
+ },
+ {
+ "id": 2811829130856901
+ },
+ {
+ "id": 2812352420645317
+ },
+ {
+ "id": 2812164953934597
+ },
+ {
+ "id": 2812160863095557
+ },
+ {
+ "id": 2813729032046789
+ },
+ {
+ "id": 2814476335547909
+ },
+ {
+ "id": 2815107864956613
+ },
+ {
+ "id": 2816013068586693
+ },
+ {
+ "id": 2816375660284933
+ },
+ {
+ "id": 2816455124847557
+ },
+ {
+ "id": 2817594853805701
+ },
+ {
+ "id": 2818031067369029
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8155,
+ "records_with_pk": 8155,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28249,
+ "records_with_pk": 28249,
+ "missing": 128,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 2796087732473349
+ },
+ {
+ "sitegoodsstockid": 2796087732375045
+ },
+ {
+ "sitegoodsstockid": 2796085792214469
+ },
+ {
+ "sitegoodsstockid": 2796085791641029
+ },
+ {
+ "sitegoodsstockid": 2796085792116165
+ },
+ {
+ "sitegoodsstockid": 2796085791542725
+ },
+ {
+ "sitegoodsstockid": 2796082589486533
+ },
+ {
+ "sitegoodsstockid": 2796082589027781
+ },
+ {
+ "sitegoodsstockid": 2796082588552645
+ },
+ {
+ "sitegoodsstockid": 2796082587995589
+ },
+ {
+ "sitegoodsstockid": 2796082587520453
+ },
+ {
+ "sitegoodsstockid": 2796082587028933
+ },
+ {
+ "sitegoodsstockid": 2796082586570181
+ },
+ {
+ "sitegoodsstockid": 2796082586013125
+ },
+ {
+ "sitegoodsstockid": 2796082585505221
+ },
+ {
+ "sitegoodsstockid": 2796082589584837
+ },
+ {
+ "sitegoodsstockid": 2796082589126085
+ },
+ {
+ "sitegoodsstockid": 2796082588650949
+ },
+ {
+ "sitegoodsstockid": 2796082588110277
+ },
+ {
+ "sitegoodsstockid": 2796082587618757
+ },
+ {
+ "sitegoodsstockid": 2796082587127237
+ },
+ {
+ "sitegoodsstockid": 2796082586668485
+ },
+ {
+ "sitegoodsstockid": 2796082586111429
+ },
+ {
+ "sitegoodsstockid": 2796082585603525
+ },
+ {
+ "sitegoodsstockid": 2796082584784325
+ },
+ {
+ "sitegoodsstockid": 2796082584292805
+ },
+ {
+ "sitegoodsstockid": 2796082583768517
+ },
+ {
+ "sitegoodsstockid": 2796082583260613
+ },
+ {
+ "sitegoodsstockid": 2796082582752709
+ },
+ {
+ "sitegoodsstockid": 2796082584686021
+ },
+ {
+ "sitegoodsstockid": 2796082584194501
+ },
+ {
+ "sitegoodsstockid": 2796082583653829
+ },
+ {
+ "sitegoodsstockid": 2796082583162309
+ },
+ {
+ "sitegoodsstockid": 2796082582654405
+ },
+ {
+ "sitegoodsstockid": 2796074872851973
+ },
+ {
+ "sitegoodsstockid": 2796074872753669
+ },
+ {
+ "sitegoodsstockid": 2796074436742661
+ },
+ {
+ "sitegoodsstockid": 2796074436578821
+ },
+ {
+ "sitegoodsstockid": 2796074059976133
+ },
+ {
+ "sitegoodsstockid": 2796074059894213
+ },
+ {
+ "sitegoodsstockid": 2796073653128709
+ },
+ {
+ "sitegoodsstockid": 2796073653030405
+ },
+ {
+ "sitegoodsstockid": 2796073284095429
+ },
+ {
+ "sitegoodsstockid": 2796073283997125
+ },
+ {
+ "sitegoodsstockid": 2796072902577605
+ },
+ {
+ "sitegoodsstockid": 2796072902675909
+ },
+ {
+ "sitegoodsstockid": 2796072030784965
+ },
+ {
+ "sitegoodsstockid": 2796072030703045
+ },
+ {
+ "sitegoodsstockid": 2796070969183685
+ },
+ {
+ "sitegoodsstockid": 2796070969298373
+ }
+ ],
+ "pages": 797,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1633,
+ "records_with_pk": 1633,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22153,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 22153,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5808,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T10:38:58.926701+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_104948.json b/etl_billiards/reports/ods_gap_check_20260115_104948.json
new file mode 100644
index 0000000..48d3e56
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_104948.json
@@ -0,0 +1,854 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T09:28:34.669129+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 50816,
+ "records_with_pk": 50816,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21513,
+ "records_with_pk": 21513,
+ "missing": 5554,
+ "missing_samples": [
+ {
+ "id": 2793005672007237
+ },
+ {
+ "id": 2794775029944453
+ },
+ {
+ "id": 2794723221669957
+ },
+ {
+ "id": 2795846081054981
+ },
+ {
+ "id": 2797170093527045
+ },
+ {
+ "id": 2797169961897989
+ },
+ {
+ "id": 2797459120852869
+ },
+ {
+ "id": 2797370356928517
+ },
+ {
+ "id": 2798636101421317
+ },
+ {
+ "id": 2798802248288261
+ },
+ {
+ "id": 2800105539552709
+ },
+ {
+ "id": 2800050273584581
+ },
+ {
+ "id": 2800462764542021
+ },
+ {
+ "id": 2800460224120773
+ },
+ {
+ "id": 2800454900648005
+ },
+ {
+ "id": 2800448023513157
+ },
+ {
+ "id": 2800442606962629
+ },
+ {
+ "id": 2800433643243525
+ },
+ {
+ "id": 2800430651182085
+ },
+ {
+ "id": 2800428852725765
+ },
+ {
+ "id": 2800423540131717
+ },
+ {
+ "id": 2800421742806917
+ },
+ {
+ "id": 2800420036233221
+ },
+ {
+ "id": 2800410925254597
+ },
+ {
+ "id": 2800410227705733
+ },
+ {
+ "id": 2800392593475653
+ },
+ {
+ "id": 2800388746184581
+ },
+ {
+ "id": 2800388462479301
+ },
+ {
+ "id": 2800383220615109
+ },
+ {
+ "id": 2800379828701189
+ },
+ {
+ "id": 2800379750893445
+ },
+ {
+ "id": 2800379609925573
+ },
+ {
+ "id": 2800378758907845
+ },
+ {
+ "id": 2800378535118789
+ },
+ {
+ "id": 2800371960039365
+ },
+ {
+ "id": 2800363039770693
+ },
+ {
+ "id": 2800360608303045
+ },
+ {
+ "id": 2800353168738309
+ },
+ {
+ "id": 2800353054263173
+ },
+ {
+ "id": 2800348877604741
+ },
+ {
+ "id": 2800348098742341
+ },
+ {
+ "id": 2800343364913157
+ },
+ {
+ "id": 2800328443021317
+ },
+ {
+ "id": 2800320895223685
+ },
+ {
+ "id": 2800316938717189
+ },
+ {
+ "id": 2800311915366341
+ },
+ {
+ "id": 2800301266225093
+ },
+ {
+ "id": 2800272176744389
+ },
+ {
+ "id": 2800265338046277
+ },
+ {
+ "id": 2800262033213317
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9751,
+ "records_with_pk": 9751,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815030085
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4415,
+ "records_with_pk": 4415,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 78,
+ "records_with_pk": 78,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11733,
+ "records_with_pk": 11733,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863811867973
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16006,
+ "records_with_pk": 16006,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2407,
+ "records_with_pk": 2407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 122,
+ "missing_samples": [
+ {
+ "id": 2800763348731909
+ },
+ {
+ "id": 2800824057628741
+ },
+ {
+ "id": 2801879399532933
+ },
+ {
+ "id": 2802064357345349
+ },
+ {
+ "id": 2802480974171333
+ },
+ {
+ "id": 2802393839258885
+ },
+ {
+ "id": 2802362619840581
+ },
+ {
+ "id": 2803649174965445
+ },
+ {
+ "id": 2803524215835845
+ },
+ {
+ "id": 2803710575593541
+ },
+ {
+ "id": 2803666932010565
+ },
+ {
+ "id": 2803661545508421
+ },
+ {
+ "id": 2804767340973317
+ },
+ {
+ "id": 2805188835477573
+ },
+ {
+ "id": 2805121951074373
+ },
+ {
+ "id": 2805111552117957
+ },
+ {
+ "id": 2805070136823365
+ },
+ {
+ "id": 2806426635208517
+ },
+ {
+ "id": 2806371278325381
+ },
+ {
+ "id": 2806244951017285
+ },
+ {
+ "id": 2806708031637381
+ },
+ {
+ "id": 2806859908384389
+ },
+ {
+ "id": 2806855233947525
+ },
+ {
+ "id": 2807891556897349
+ },
+ {
+ "id": 2807815241847557
+ },
+ {
+ "id": 2807912803045957
+ },
+ {
+ "id": 2807909672309637
+ },
+ {
+ "id": 2808923174783109
+ },
+ {
+ "id": 2809187656829061
+ },
+ {
+ "id": 2809504839059909
+ },
+ {
+ "id": 2809471788321221
+ },
+ {
+ "id": 2809392429549765
+ },
+ {
+ "id": 2810371281799621
+ },
+ {
+ "id": 2810563362048453
+ },
+ {
+ "id": 2810546930207237
+ },
+ {
+ "id": 2810412839373574
+ },
+ {
+ "id": 2810801124133381
+ },
+ {
+ "id": 2810800364193989
+ },
+ {
+ "id": 2811829130856901
+ },
+ {
+ "id": 2812352420645317
+ },
+ {
+ "id": 2812164953934597
+ },
+ {
+ "id": 2812160863095557
+ },
+ {
+ "id": 2813729032046789
+ },
+ {
+ "id": 2814476335547909
+ },
+ {
+ "id": 2815107864956613
+ },
+ {
+ "id": 2816013068586693
+ },
+ {
+ "id": 2816375660284933
+ },
+ {
+ "id": 2816455124847557
+ },
+ {
+ "id": 2817594853805701
+ },
+ {
+ "id": 2818031067369029
+ }
+ ],
+ "pages": 794,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8155,
+ "records_with_pk": 8155,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28249,
+ "records_with_pk": 28249,
+ "missing": 128,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 2796087732473349
+ },
+ {
+ "sitegoodsstockid": 2796087732375045
+ },
+ {
+ "sitegoodsstockid": 2796085792214469
+ },
+ {
+ "sitegoodsstockid": 2796085791641029
+ },
+ {
+ "sitegoodsstockid": 2796085792116165
+ },
+ {
+ "sitegoodsstockid": 2796085791542725
+ },
+ {
+ "sitegoodsstockid": 2796082589486533
+ },
+ {
+ "sitegoodsstockid": 2796082589027781
+ },
+ {
+ "sitegoodsstockid": 2796082588552645
+ },
+ {
+ "sitegoodsstockid": 2796082587995589
+ },
+ {
+ "sitegoodsstockid": 2796082587520453
+ },
+ {
+ "sitegoodsstockid": 2796082587028933
+ },
+ {
+ "sitegoodsstockid": 2796082586570181
+ },
+ {
+ "sitegoodsstockid": 2796082586013125
+ },
+ {
+ "sitegoodsstockid": 2796082585505221
+ },
+ {
+ "sitegoodsstockid": 2796082589584837
+ },
+ {
+ "sitegoodsstockid": 2796082589126085
+ },
+ {
+ "sitegoodsstockid": 2796082588650949
+ },
+ {
+ "sitegoodsstockid": 2796082588110277
+ },
+ {
+ "sitegoodsstockid": 2796082587618757
+ },
+ {
+ "sitegoodsstockid": 2796082587127237
+ },
+ {
+ "sitegoodsstockid": 2796082586668485
+ },
+ {
+ "sitegoodsstockid": 2796082586111429
+ },
+ {
+ "sitegoodsstockid": 2796082585603525
+ },
+ {
+ "sitegoodsstockid": 2796082584784325
+ },
+ {
+ "sitegoodsstockid": 2796082584292805
+ },
+ {
+ "sitegoodsstockid": 2796082583768517
+ },
+ {
+ "sitegoodsstockid": 2796082583260613
+ },
+ {
+ "sitegoodsstockid": 2796082582752709
+ },
+ {
+ "sitegoodsstockid": 2796082584686021
+ },
+ {
+ "sitegoodsstockid": 2796082584194501
+ },
+ {
+ "sitegoodsstockid": 2796082583653829
+ },
+ {
+ "sitegoodsstockid": 2796082583162309
+ },
+ {
+ "sitegoodsstockid": 2796082582654405
+ },
+ {
+ "sitegoodsstockid": 2796074872851973
+ },
+ {
+ "sitegoodsstockid": 2796074872753669
+ },
+ {
+ "sitegoodsstockid": 2796074436742661
+ },
+ {
+ "sitegoodsstockid": 2796074436578821
+ },
+ {
+ "sitegoodsstockid": 2796074059976133
+ },
+ {
+ "sitegoodsstockid": 2796074059894213
+ },
+ {
+ "sitegoodsstockid": 2796073653128709
+ },
+ {
+ "sitegoodsstockid": 2796073653030405
+ },
+ {
+ "sitegoodsstockid": 2796073284095429
+ },
+ {
+ "sitegoodsstockid": 2796073283997125
+ },
+ {
+ "sitegoodsstockid": 2796072902577605
+ },
+ {
+ "sitegoodsstockid": 2796072902675909
+ },
+ {
+ "sitegoodsstockid": 2796072030784965
+ },
+ {
+ "sitegoodsstockid": 2796072030703045
+ },
+ {
+ "sitegoodsstockid": 2796070969183685
+ },
+ {
+ "sitegoodsstockid": 2796070969298373
+ }
+ ],
+ "pages": 797,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1633,
+ "records_with_pk": 1633,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22153,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 794,
+ "skipped_missing_pk": 22153,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 5808,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T10:49:48.767932+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_131821.json b/etl_billiards/reports/ods_gap_check_20260115_131821.json
new file mode 100644
index 0000000..15f3a8f
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_131821.json
@@ -0,0 +1,466 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T12:26:36.334001+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 50880,
+ "records_with_pk": 50880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21514,
+ "records_with_pk": 21514,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052076252251589
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9752,
+ "records_with_pk": 9752,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052128803980869
+ },
+ {
+ "id": 3051863815030085
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4415,
+ "records_with_pk": 4415,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 78,
+ "records_with_pk": 78,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11736,
+ "records_with_pk": 11736,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3052137658025541
+ },
+ {
+ "id": 3052128801408581
+ },
+ {
+ "id": 3052076274943365
+ },
+ {
+ "id": 3051863811867973
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16013,
+ "records_with_pk": 16013,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "id": 3052120802903429
+ },
+ {
+ "id": 3052110365689221
+ },
+ {
+ "id": 3052091273414213
+ },
+ {
+ "id": 3052081711859141
+ },
+ {
+ "id": 3052063649959365
+ },
+ {
+ "id": 3052026368034565
+ }
+ ],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2407,
+ "records_with_pk": 2407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 2832289312279685
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8157,
+ "records_with_pk": 8157,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052142428931461
+ },
+ {
+ "id": 3052128804521541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28255,
+ "records_with_pk": 28255,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052076276811141
+ },
+ {
+ "sitegoodsstockid": 3052076276630917
+ },
+ {
+ "sitegoodsstockid": 3052093657615493
+ },
+ {
+ "sitegoodsstockid": 3052093657549957
+ },
+ {
+ "sitegoodsstockid": 3052090913623365
+ },
+ {
+ "sitegoodsstockid": 3052090913557829
+ }
+ ],
+ "pages": 798,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1633,
+ "records_with_pk": 1633,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22154,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 22154,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 24,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T13:18:21.158800+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_161345.json b/etl_billiards/reports/ods_gap_check_20260115_161345.json
new file mode 100644
index 0000000..3e51576
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_161345.json
@@ -0,0 +1,637 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T15:20:49.891695+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 50880,
+ "records_with_pk": 50880,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21529,
+ "records_with_pk": 21529,
+ "missing": 16,
+ "missing_samples": [
+ {
+ "id": 3052076252251589
+ },
+ {
+ "id": 3052248841586181
+ },
+ {
+ "id": 3052246644557253
+ },
+ {
+ "id": 3052208895166021
+ },
+ {
+ "id": 3052208828270085
+ },
+ {
+ "id": 3052206795720133
+ },
+ {
+ "id": 3052201188050501
+ },
+ {
+ "id": 3052180955448837
+ },
+ {
+ "id": 3052173364315589
+ },
+ {
+ "id": 3052163277669957
+ },
+ {
+ "id": 3052163174696517
+ },
+ {
+ "id": 3052147004147205
+ },
+ {
+ "id": 3052142531233349
+ },
+ {
+ "id": 3052142411367877
+ },
+ {
+ "id": 3052137630057989
+ },
+ {
+ "id": 3052128780748293
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9766,
+ "records_with_pk": 9766,
+ "missing": 16,
+ "missing_samples": [
+ {
+ "id": 3052300682069957
+ },
+ {
+ "id": 3052294634882885
+ },
+ {
+ "id": 3052248857986437
+ },
+ {
+ "id": 3052246666462789
+ },
+ {
+ "id": 3052208915236357
+ },
+ {
+ "id": 3052208850044485
+ },
+ {
+ "id": 3052201204237701
+ },
+ {
+ "id": 3052180970997125
+ },
+ {
+ "id": 3052173380224389
+ },
+ {
+ "id": 3052163300967941
+ },
+ {
+ "id": 3052163191883269
+ },
+ {
+ "id": 3052147159025221
+ },
+ {
+ "id": 3052142428374405
+ },
+ {
+ "id": 3052137660286533
+ },
+ {
+ "id": 3052128803980869
+ },
+ {
+ "id": 3051863815030085
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4415,
+ "records_with_pk": 4415,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 78,
+ "records_with_pk": 78,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11751,
+ "records_with_pk": 11751,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3052300679546821
+ },
+ {
+ "id": 3052294632818501
+ },
+ {
+ "id": 3052248855692677
+ },
+ {
+ "id": 3052246663988805
+ },
+ {
+ "id": 3052208912549381
+ },
+ {
+ "id": 3052208847406661
+ },
+ {
+ "id": 3052206817199493
+ },
+ {
+ "id": 3052201201649029
+ },
+ {
+ "id": 3052180968310149
+ },
+ {
+ "id": 3052173377963397
+ },
+ {
+ "id": 3052163298772485
+ },
+ {
+ "id": 3052163189163525
+ },
+ {
+ "id": 3052147156256325
+ },
+ {
+ "id": 3052142551893573
+ },
+ {
+ "id": 3052142425949573
+ },
+ {
+ "id": 3052137658025541
+ },
+ {
+ "id": 3052128801408581
+ },
+ {
+ "id": 3052076274943365
+ },
+ {
+ "id": 3051863811867973
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16036,
+ "records_with_pk": 16036,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052311888218053
+ },
+ {
+ "id": 3052310918104901
+ },
+ {
+ "id": 3052305891788677
+ }
+ ],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2407,
+ "records_with_pk": 2407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 2832289312279685
+ }
+ ],
+ "pages": 795,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8168,
+ "records_with_pk": 8168,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3052300682807237
+ },
+ {
+ "id": 3052294635407173
+ },
+ {
+ "id": 3052248858707333
+ },
+ {
+ "id": 3052246667150917
+ },
+ {
+ "id": 3052208915777029
+ },
+ {
+ "id": 3052208850716229
+ },
+ {
+ "id": 3052201204778373
+ },
+ {
+ "id": 3052180971554181
+ },
+ {
+ "id": 3052173380846981
+ },
+ {
+ "id": 3052163301492229
+ },
+ {
+ "id": 3052163192456709
+ },
+ {
+ "id": 3052142428931461
+ },
+ {
+ "id": 3052128804521541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28260,
+ "records_with_pk": 28260,
+ "missing": 11,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052076276811141
+ },
+ {
+ "sitegoodsstockid": 3052076276630917
+ },
+ {
+ "sitegoodsstockid": 3052243917669893
+ },
+ {
+ "sitegoodsstockid": 3052222543218053
+ },
+ {
+ "sitegoodsstockid": 3052206819034501
+ },
+ {
+ "sitegoodsstockid": 3052142553990725
+ },
+ {
+ "sitegoodsstockid": 3052142553810501
+ },
+ {
+ "sitegoodsstockid": 3052093657615493
+ },
+ {
+ "sitegoodsstockid": 3052093657549957
+ },
+ {
+ "sitegoodsstockid": 3052090913623365
+ },
+ {
+ "sitegoodsstockid": 3052090913557829
+ }
+ ],
+ "pages": 798,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1633,
+ "records_with_pk": 1633,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22169,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 795,
+ "skipped_missing_pk": 22169,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 81,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T16:13:45.329617+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_162208.json b/etl_billiards/reports/ods_gap_check_20260115_162208.json
new file mode 100644
index 0000000..60e80b5
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_162208.json
@@ -0,0 +1,666 @@
+{
+ "start": "2026-01-01T00:00:00+08:00",
+ "end": "2026-01-15T16:15:44.950334+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 3776,
+ "records_with_pk": 3776,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1607,
+ "records_with_pk": 1607,
+ "missing": 19,
+ "missing_samples": [
+ {
+ "id": 3052076252251589
+ },
+ {
+ "id": 3052322370635653
+ },
+ {
+ "id": 3052300651513733
+ },
+ {
+ "id": 3052294618351365
+ },
+ {
+ "id": 3052248841586181
+ },
+ {
+ "id": 3052246644557253
+ },
+ {
+ "id": 3052208895166021
+ },
+ {
+ "id": 3052208828270085
+ },
+ {
+ "id": 3052206795720133
+ },
+ {
+ "id": 3052201188050501
+ },
+ {
+ "id": 3052180955448837
+ },
+ {
+ "id": 3052173364315589
+ },
+ {
+ "id": 3052163277669957
+ },
+ {
+ "id": 3052163174696517
+ },
+ {
+ "id": 3052147004147205
+ },
+ {
+ "id": 3052142531233349
+ },
+ {
+ "id": 3052142411367877
+ },
+ {
+ "id": 3052137630057989
+ },
+ {
+ "id": 3052128780748293
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9767,
+ "records_with_pk": 9767,
+ "missing": 17,
+ "missing_samples": [
+ {
+ "id": 3052322387674885
+ },
+ {
+ "id": 3052300682069957
+ },
+ {
+ "id": 3052294634882885
+ },
+ {
+ "id": 3052248857986437
+ },
+ {
+ "id": 3052246666462789
+ },
+ {
+ "id": 3052208915236357
+ },
+ {
+ "id": 3052208850044485
+ },
+ {
+ "id": 3052201204237701
+ },
+ {
+ "id": 3052180970997125
+ },
+ {
+ "id": 3052173380224389
+ },
+ {
+ "id": 3052163300967941
+ },
+ {
+ "id": 3052163191883269
+ },
+ {
+ "id": 3052147159025221
+ },
+ {
+ "id": 3052142428374405
+ },
+ {
+ "id": 3052137660286533
+ },
+ {
+ "id": 3052128803980869
+ },
+ {
+ "id": 3051863815030085
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 357,
+ "records_with_pk": 357,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 24,
+ "records_with_pk": 24,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11752,
+ "records_with_pk": 11752,
+ "missing": 20,
+ "missing_samples": [
+ {
+ "id": 3052322385266437
+ },
+ {
+ "id": 3052300679546821
+ },
+ {
+ "id": 3052294632818501
+ },
+ {
+ "id": 3052248855692677
+ },
+ {
+ "id": 3052246663988805
+ },
+ {
+ "id": 3052208912549381
+ },
+ {
+ "id": 3052208847406661
+ },
+ {
+ "id": 3052206817199493
+ },
+ {
+ "id": 3052201201649029
+ },
+ {
+ "id": 3052180968310149
+ },
+ {
+ "id": 3052173377963397
+ },
+ {
+ "id": 3052163298772485
+ },
+ {
+ "id": 3052163189163525
+ },
+ {
+ "id": 3052147156256325
+ },
+ {
+ "id": 3052142551893573
+ },
+ {
+ "id": 3052142425949573
+ },
+ {
+ "id": 3052137658025541
+ },
+ {
+ "id": 3052128801408581
+ },
+ {
+ "id": 3052076274943365
+ },
+ {
+ "id": 3051863811867973
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16038,
+ "records_with_pk": 16038,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3052337405658950
+ },
+ {
+ "id": 3052337405658949
+ },
+ {
+ "id": 3052311888218053
+ },
+ {
+ "id": 3052310918104901
+ },
+ {
+ "id": 3052305891788677
+ }
+ ],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2407,
+ "records_with_pk": 2407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 34,
+ "records_with_pk": 34,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8175,
+ "records_with_pk": 8175,
+ "missing": 14,
+ "missing_samples": [
+ {
+ "id": 3052322388297477
+ },
+ {
+ "id": 3052300682807237
+ },
+ {
+ "id": 3052294635407173
+ },
+ {
+ "id": 3052248858707333
+ },
+ {
+ "id": 3052246667150917
+ },
+ {
+ "id": 3052208915777029
+ },
+ {
+ "id": 3052208850716229
+ },
+ {
+ "id": 3052201204778373
+ },
+ {
+ "id": 3052180971554181
+ },
+ {
+ "id": 3052173380846981
+ },
+ {
+ "id": 3052163301492229
+ },
+ {
+ "id": 3052163192456709
+ },
+ {
+ "id": 3052142428931461
+ },
+ {
+ "id": 3052128804521541
+ }
+ ],
+ "pages": 41,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 2121,
+ "records_with_pk": 2121,
+ "missing": 14,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052076276811141
+ },
+ {
+ "sitegoodsstockid": 3052076276630917
+ },
+ {
+ "sitegoodsstockid": 3052287917508421
+ },
+ {
+ "sitegoodsstockid": 3052287916263237
+ },
+ {
+ "sitegoodsstockid": 3052287914215237
+ },
+ {
+ "sitegoodsstockid": 3052243917669893
+ },
+ {
+ "sitegoodsstockid": 3052222543218053
+ },
+ {
+ "sitegoodsstockid": 3052206819034501
+ },
+ {
+ "sitegoodsstockid": 3052142553990725
+ },
+ {
+ "sitegoodsstockid": 3052142553810501
+ },
+ {
+ "sitegoodsstockid": 3052093657615493
+ },
+ {
+ "sitegoodsstockid": 3052093657549957
+ },
+ {
+ "sitegoodsstockid": 3052090913623365
+ },
+ {
+ "sitegoodsstockid": 3052090913557829
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1633,
+ "records_with_pk": 1633,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 1656,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 59,
+ "skipped_missing_pk": 1656,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 91,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T16:22:08.953307+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_185455.json b/etl_billiards/reports/ods_gap_check_20260115_185455.json
new file mode 100644
index 0000000..63b4d06
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_185455.json
@@ -0,0 +1,793 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T18:31:28.819229+08:00",
+ "cutoff": null,
+ "window_days": 1,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 12736,
+ "records_with_pk": 12736,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21555,
+ "records_with_pk": 21555,
+ "missing": 20,
+ "missing_samples": [
+ {
+ "id": 3052456015579909
+ },
+ {
+ "id": 3052454986812421
+ },
+ {
+ "id": 3052451320171589
+ },
+ {
+ "id": 3052450396441349
+ },
+ {
+ "id": 3052435016272581
+ },
+ {
+ "id": 3052434918165573
+ },
+ {
+ "id": 3052434834279173
+ },
+ {
+ "id": 3052424705084101
+ },
+ {
+ "id": 3052424301988549
+ },
+ {
+ "id": 3052422092426309
+ },
+ {
+ "id": 3052422042291205
+ },
+ {
+ "id": 3052416805587717
+ },
+ {
+ "id": 3052416349539013
+ },
+ {
+ "id": 3052414381706245
+ },
+ {
+ "id": 3052405284129477
+ },
+ {
+ "id": 3052372817201861
+ },
+ {
+ "id": 3052370135074565
+ },
+ {
+ "id": 3052365518669701
+ },
+ {
+ "id": 3052360602781445
+ },
+ {
+ "id": 3052348366227269
+ }
+ ],
+ "pages": 202,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9790,
+ "records_with_pk": 9790,
+ "missing": 13,
+ "missing_samples": [
+ {
+ "id": 3052456031243333
+ },
+ {
+ "id": 3052455010716357
+ },
+ {
+ "id": 3052450413448261
+ },
+ {
+ "id": 3052435034573573
+ },
+ {
+ "id": 3052434948410437
+ },
+ {
+ "id": 3052434862345285
+ },
+ {
+ "id": 3052424721894149
+ },
+ {
+ "id": 3052422108547781
+ },
+ {
+ "id": 3052422059330309
+ },
+ {
+ "id": 3052416822201413
+ },
+ {
+ "id": 3052416383371973
+ },
+ {
+ "id": 3052414398089989
+ },
+ {
+ "id": 3052405301316293
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4416,
+ "records_with_pk": 4416,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052424373423109
+ },
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 7,
+ "records_with_pk": 7,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 126,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/AssistantPerformance/GetAbolitionAssistant"
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/TenantGoods/GetGoodsSalesList"
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/PayLog/GetPayLogListPage"
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16058,
+ "records_with_pk": 16058,
+ "missing": 25,
+ "missing_samples": [
+ {
+ "id": 3052472789158981
+ },
+ {
+ "id": 3052464759196741
+ },
+ {
+ "id": 3052449213533253
+ },
+ {
+ "id": 3052427220864005
+ },
+ {
+ "id": 3052423892765381
+ },
+ {
+ "id": 3052423497239621
+ },
+ {
+ "id": 3052423330941957
+ },
+ {
+ "id": 3052423193480197
+ },
+ {
+ "id": 3052421983881925
+ },
+ {
+ "id": 3052417450494725
+ },
+ {
+ "id": 3052391048710853
+ },
+ {
+ "id": 3052375480896197
+ },
+ {
+ "id": 3052373085588229
+ },
+ {
+ "id": 3052365403277253
+ },
+ {
+ "id": 3052363066066885
+ },
+ {
+ "id": 3052362943629253
+ },
+ {
+ "id": 3052360961984261
+ },
+ {
+ "id": 3052357851465478
+ },
+ {
+ "id": 3052355338749893
+ },
+ {
+ "id": 3052345004771077
+ },
+ {
+ "id": 3052337405658950
+ },
+ {
+ "id": 3052337405658949
+ },
+ {
+ "id": 3052311888218053
+ },
+ {
+ "id": 3052310918104901
+ },
+ {
+ "id": 3052305891788677
+ }
+ ],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2408,
+ "records_with_pk": 2408,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052424371244037
+ },
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 2832289312279685
+ }
+ ],
+ "pages": 199,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8201,
+ "records_with_pk": 8201,
+ "missing": 46,
+ "missing_samples": [
+ {
+ "id": 3052482484392069
+ },
+ {
+ "id": 3052481203670085
+ },
+ {
+ "id": 3052476693515333
+ },
+ {
+ "id": 3052456031882310
+ },
+ {
+ "id": 3052456031882309
+ },
+ {
+ "id": 3052455011551941
+ },
+ {
+ "id": 3052450414201925
+ },
+ {
+ "id": 3052435035147014
+ },
+ {
+ "id": 3052435035147013
+ },
+ {
+ "id": 3052434949147717
+ },
+ {
+ "id": 3052434862902341
+ },
+ {
+ "id": 3052424722467589
+ },
+ {
+ "id": 3052422109268677
+ },
+ {
+ "id": 3052422059936517
+ },
+ {
+ "id": 3052416823086149
+ },
+ {
+ "id": 3052416384174790
+ },
+ {
+ "id": 3052416384174789
+ },
+ {
+ "id": 3052414398679813
+ },
+ {
+ "id": 3052405301840581
+ },
+ {
+ "id": 3052372838681349
+ },
+ {
+ "id": 3052370153048005
+ },
+ {
+ "id": 3052365536249669
+ },
+ {
+ "id": 3052360620558278
+ },
+ {
+ "id": 3052360620558277
+ },
+ {
+ "id": 3052348384495366
+ },
+ {
+ "id": 3052348384495365
+ },
+ {
+ "id": 3052339892700998
+ },
+ {
+ "id": 3052339892700997
+ },
+ {
+ "id": 3052339838781254
+ },
+ {
+ "id": 3052339838781253
+ },
+ {
+ "id": 3052339780601670
+ },
+ {
+ "id": 3052339780601669
+ },
+ {
+ "id": 3052322388297477
+ },
+ {
+ "id": 3052300682807237
+ },
+ {
+ "id": 3052294635407173
+ },
+ {
+ "id": 3052248858707333
+ },
+ {
+ "id": 3052246667150917
+ },
+ {
+ "id": 3052208915777029
+ },
+ {
+ "id": 3052208850716229
+ },
+ {
+ "id": 3052201204778373
+ },
+ {
+ "id": 3052180971554181
+ },
+ {
+ "id": 3052173380846981
+ },
+ {
+ "id": 3052163301492229
+ },
+ {
+ "id": 3052163192456709
+ },
+ {
+ "id": 3052142428931461
+ },
+ {
+ "id": 3052128804521541
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28272,
+ "records_with_pk": 28272,
+ "missing": 23,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052458794765381
+ },
+ {
+ "sitegoodsstockid": 3052451366964229
+ },
+ {
+ "sitegoodsstockid": 3052421675027205
+ },
+ {
+ "sitegoodsstockid": 3052421675502341
+ },
+ {
+ "sitegoodsstockid": 3052386208909957
+ },
+ {
+ "sitegoodsstockid": 3052386208975493
+ },
+ {
+ "sitegoodsstockid": 3052365069420485
+ },
+ {
+ "sitegoodsstockid": 3052363193403333
+ },
+ {
+ "sitegoodsstockid": 3052350941661061
+ },
+ {
+ "sitegoodsstockid": 3052287914215237
+ },
+ {
+ "sitegoodsstockid": 3052287916263237
+ },
+ {
+ "sitegoodsstockid": 3052287917508421
+ },
+ {
+ "sitegoodsstockid": 3052243917669893
+ },
+ {
+ "sitegoodsstockid": 3052222543218053
+ },
+ {
+ "sitegoodsstockid": 3052206819034501
+ },
+ {
+ "sitegoodsstockid": 3052142553990725
+ },
+ {
+ "sitegoodsstockid": 3052142553810501
+ },
+ {
+ "sitegoodsstockid": 3052093657549957
+ },
+ {
+ "sitegoodsstockid": 3052093657615493
+ },
+ {
+ "sitegoodsstockid": 3052090913557829
+ },
+ {
+ "sitegoodsstockid": 3052090913623365
+ },
+ {
+ "sitegoodsstockid": 3052076276811141
+ },
+ {
+ "sitegoodsstockid": 3052076276630917
+ }
+ ],
+ "pages": 238,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1634,
+ "records_with_pk": 1634,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052476605991685
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22193,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 203,
+ "skipped_missing_pk": 22193,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 133,
+ "total_errors": 3,
+ "generated_at": "2026-01-15T18:54:55.925533+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_190203.json b/etl_billiards/reports/ods_gap_check_20260115_190203.json
new file mode 100644
index 0000000..1a6785f
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_190203.json
@@ -0,0 +1,933 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T18:54:48.797928+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21561,
+ "records_with_pk": 21561,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3052486983602373
+ },
+ {
+ "id": 3052486257037317
+ },
+ {
+ "id": 3052482466484421
+ },
+ {
+ "id": 3052481176259653
+ },
+ {
+ "id": 3052476676655813
+ },
+ {
+ "id": 3052476470053893
+ },
+ {
+ "id": 3052456015579909
+ },
+ {
+ "id": 3052454986812421
+ },
+ {
+ "id": 3052451320171589
+ },
+ {
+ "id": 3052450396441349
+ },
+ {
+ "id": 3052435016272581
+ },
+ {
+ "id": 3052434918165573
+ },
+ {
+ "id": 3052434834279173
+ },
+ {
+ "id": 3052424705084101
+ },
+ {
+ "id": 3052424301988549
+ },
+ {
+ "id": 3052422092426309
+ },
+ {
+ "id": 3052422042291205
+ },
+ {
+ "id": 3052416805587717
+ },
+ {
+ "id": 3052416349539013
+ },
+ {
+ "id": 3052414381706245
+ },
+ {
+ "id": 3052405284129477
+ },
+ {
+ "id": 3052372817201861
+ },
+ {
+ "id": 3052370135074565
+ },
+ {
+ "id": 3052365518669701
+ },
+ {
+ "id": 3052360602781445
+ },
+ {
+ "id": 3052348366227269
+ }
+ ],
+ "pages": 113,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9793,
+ "records_with_pk": 9793,
+ "missing": 18,
+ "missing_samples": [
+ {
+ "id": 3052486277812357
+ },
+ {
+ "id": 3052482483671173
+ },
+ {
+ "id": 3052481203047493
+ },
+ {
+ "id": 3052476692925509
+ },
+ {
+ "id": 3052476604599045
+ },
+ {
+ "id": 3052456031243333
+ },
+ {
+ "id": 3052455010716357
+ },
+ {
+ "id": 3052450413448261
+ },
+ {
+ "id": 3052435034573573
+ },
+ {
+ "id": 3052434948410437
+ },
+ {
+ "id": 3052434862345285
+ },
+ {
+ "id": 3052424721894149
+ },
+ {
+ "id": 3052422108547781
+ },
+ {
+ "id": 3052422059330309
+ },
+ {
+ "id": 3052416822201413
+ },
+ {
+ "id": 3052416383371973
+ },
+ {
+ "id": 3052414398089989
+ },
+ {
+ "id": 3052405301316293
+ }
+ ],
+ "pages": 49,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4417,
+ "records_with_pk": 4417,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052476605221637
+ },
+ {
+ "id": 3052424373423109
+ },
+ {
+ "id": 3051863815488837
+ }
+ ],
+ "pages": 27,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 78,
+ "records_with_pk": 78,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11782,
+ "records_with_pk": 11782,
+ "missing": 22,
+ "missing_samples": [
+ {
+ "id": 3052487098585157
+ },
+ {
+ "id": 3052486275354757
+ },
+ {
+ "id": 3052485074505861
+ },
+ {
+ "id": 3052482481311877
+ },
+ {
+ "id": 3052481200557125
+ },
+ {
+ "id": 3052476690648133
+ },
+ {
+ "id": 3052476601436933
+ },
+ {
+ "id": 3052456028834885
+ },
+ {
+ "id": 3052455008340677
+ },
+ {
+ "id": 3052451365391365
+ },
+ {
+ "id": 3052450411056197
+ },
+ {
+ "id": 3052435032001285
+ },
+ {
+ "id": 3052434945952837
+ },
+ {
+ "id": 3052434860067909
+ },
+ {
+ "id": 3052424719502085
+ },
+ {
+ "id": 3052424370719749
+ },
+ {
+ "id": 3052422106254021
+ },
+ {
+ "id": 3052422056758021
+ },
+ {
+ "id": 3052416819645509
+ },
+ {
+ "id": 3052416380701381
+ },
+ {
+ "id": 3052414395091717
+ },
+ {
+ "id": 3052405299120837
+ }
+ ],
+ "pages": 59,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16059,
+ "records_with_pk": 16059,
+ "missing": 26,
+ "missing_samples": [
+ {
+ "id": 3052494575456325
+ },
+ {
+ "id": 3052472789158981
+ },
+ {
+ "id": 3052464759196741
+ },
+ {
+ "id": 3052449213533253
+ },
+ {
+ "id": 3052427220864005
+ },
+ {
+ "id": 3052423892765381
+ },
+ {
+ "id": 3052423497239621
+ },
+ {
+ "id": 3052423330941957
+ },
+ {
+ "id": 3052423193480197
+ },
+ {
+ "id": 3052421983881925
+ },
+ {
+ "id": 3052417450494725
+ },
+ {
+ "id": 3052391048710853
+ },
+ {
+ "id": 3052375480896197
+ },
+ {
+ "id": 3052373085588229
+ },
+ {
+ "id": 3052365403277253
+ },
+ {
+ "id": 3052363066066885
+ },
+ {
+ "id": 3052362943629253
+ },
+ {
+ "id": 3052360961984261
+ },
+ {
+ "id": 3052357851465478
+ },
+ {
+ "id": 3052355338749893
+ },
+ {
+ "id": 3052345004771077
+ },
+ {
+ "id": 3052337405658950
+ },
+ {
+ "id": 3052337405658949
+ },
+ {
+ "id": 3052311888218053
+ },
+ {
+ "id": 3052310918104901
+ },
+ {
+ "id": 3052305891788677
+ }
+ ],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2411,
+ "records_with_pk": 2411,
+ "missing": 5,
+ "missing_samples": [
+ {
+ "id": 3052487099273285
+ },
+ {
+ "id": 3052486652465285
+ },
+ {
+ "id": 3052485075095685
+ },
+ {
+ "id": 3052424371244037
+ },
+ {
+ "id": 3051863812408645
+ }
+ ],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 405,
+ "records_with_pk": 405,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 2832289312279685
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8202,
+ "records_with_pk": 8202,
+ "missing": 47,
+ "missing_samples": [
+ {
+ "id": 3052486278779013
+ },
+ {
+ "id": 3052482484392069
+ },
+ {
+ "id": 3052481203670085
+ },
+ {
+ "id": 3052476693515333
+ },
+ {
+ "id": 3052456031882310
+ },
+ {
+ "id": 3052456031882309
+ },
+ {
+ "id": 3052455011551941
+ },
+ {
+ "id": 3052450414201925
+ },
+ {
+ "id": 3052435035147014
+ },
+ {
+ "id": 3052435035147013
+ },
+ {
+ "id": 3052434949147717
+ },
+ {
+ "id": 3052434862902341
+ },
+ {
+ "id": 3052424722467589
+ },
+ {
+ "id": 3052422109268677
+ },
+ {
+ "id": 3052422059936517
+ },
+ {
+ "id": 3052416823086149
+ },
+ {
+ "id": 3052416384174790
+ },
+ {
+ "id": 3052416384174789
+ },
+ {
+ "id": 3052414398679813
+ },
+ {
+ "id": 3052405301840581
+ },
+ {
+ "id": 3052372838681349
+ },
+ {
+ "id": 3052370153048005
+ },
+ {
+ "id": 3052365536249669
+ },
+ {
+ "id": 3052360620558278
+ },
+ {
+ "id": 3052360620558277
+ },
+ {
+ "id": 3052348384495366
+ },
+ {
+ "id": 3052348384495365
+ },
+ {
+ "id": 3052339892700998
+ },
+ {
+ "id": 3052339892700997
+ },
+ {
+ "id": 3052339838781254
+ },
+ {
+ "id": 3052339838781253
+ },
+ {
+ "id": 3052339780601670
+ },
+ {
+ "id": 3052339780601669
+ },
+ {
+ "id": 3052322388297477
+ },
+ {
+ "id": 3052300682807237
+ },
+ {
+ "id": 3052294635407173
+ },
+ {
+ "id": 3052248858707333
+ },
+ {
+ "id": 3052246667150917
+ },
+ {
+ "id": 3052208915777029
+ },
+ {
+ "id": 3052208850716229
+ },
+ {
+ "id": 3052201204778373
+ },
+ {
+ "id": 3052180971554181
+ },
+ {
+ "id": 3052173380846981
+ },
+ {
+ "id": 3052163301492229
+ },
+ {
+ "id": 3052163192456709
+ },
+ {
+ "id": 3052142428931461
+ },
+ {
+ "id": 3052128804521541
+ }
+ ],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28279,
+ "records_with_pk": 28279,
+ "missing": 30,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052488613105733
+ },
+ {
+ "sitegoodsstockid": 3052486962778117
+ },
+ {
+ "sitegoodsstockid": 3052486963220485
+ },
+ {
+ "sitegoodsstockid": 3052486849335429
+ },
+ {
+ "sitegoodsstockid": 3052486782881797
+ },
+ {
+ "sitegoodsstockid": 3052485076586629
+ },
+ {
+ "sitegoodsstockid": 3052485076783237
+ },
+ {
+ "sitegoodsstockid": 3052458794765381
+ },
+ {
+ "sitegoodsstockid": 3052451366964229
+ },
+ {
+ "sitegoodsstockid": 3052421675027205
+ },
+ {
+ "sitegoodsstockid": 3052421675502341
+ },
+ {
+ "sitegoodsstockid": 3052386208909957
+ },
+ {
+ "sitegoodsstockid": 3052386208975493
+ },
+ {
+ "sitegoodsstockid": 3052365069420485
+ },
+ {
+ "sitegoodsstockid": 3052363193403333
+ },
+ {
+ "sitegoodsstockid": 3052350941661061
+ },
+ {
+ "sitegoodsstockid": 3052287914215237
+ },
+ {
+ "sitegoodsstockid": 3052287916263237
+ },
+ {
+ "sitegoodsstockid": 3052287917508421
+ },
+ {
+ "sitegoodsstockid": 3052243917669893
+ },
+ {
+ "sitegoodsstockid": 3052222543218053
+ },
+ {
+ "sitegoodsstockid": 3052206819034501
+ },
+ {
+ "sitegoodsstockid": 3052142553990725
+ },
+ {
+ "sitegoodsstockid": 3052142553810501
+ },
+ {
+ "sitegoodsstockid": 3052093657549957
+ },
+ {
+ "sitegoodsstockid": 3052093657615493
+ },
+ {
+ "sitegoodsstockid": 3052090913557829
+ },
+ {
+ "sitegoodsstockid": 3052090913623365
+ },
+ {
+ "sitegoodsstockid": 3052076276811141
+ },
+ {
+ "sitegoodsstockid": 3052076276630917
+ }
+ ],
+ "pages": 145,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1634,
+ "records_with_pk": 1634,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052476605991685
+ }
+ ],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22200,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 116,
+ "skipped_missing_pk": 22200,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 179,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T19:02:03.451627+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_222742.json b/etl_billiards/reports/ods_gap_check_20260115_222742.json
new file mode 100644
index 0000000..c1b01ca
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_222742.json
@@ -0,0 +1,402 @@
+{
+ "start": "2026-01-14T00:00:00+08:00",
+ "end": "2026-01-15T22:24:35.980217+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 64,
+ "records_with_pk": 64,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 219,
+ "records_with_pk": 219,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052693070926021
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9822,
+ "records_with_pk": 9822,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052693089456133
+ }
+ ],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 63,
+ "records_with_pk": 63,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052536228843589
+ }
+ ],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11814,
+ "records_with_pk": 11814,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16080,
+ "records_with_pk": 16080,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 81,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 5,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2421,
+ "records_with_pk": 2421,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 13,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8223,
+ "records_with_pk": 8223,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 258,
+ "records_with_pk": 258,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052693659717701
+ }
+ ],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1640,
+ "records_with_pk": 1640,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 227,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 227,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 4,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T22:27:42.389451+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_223929.json b/etl_billiards/reports/ods_gap_check_20260115_223929.json
new file mode 100644
index 0000000..027aa5c
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_223929.json
@@ -0,0 +1,409 @@
+{
+ "start": "2026-01-14T00:00:00+08:00",
+ "end": "2026-01-15T22:34:02.852100+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 64,
+ "records_with_pk": 64,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 219,
+ "records_with_pk": 219,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9822,
+ "records_with_pk": 9822,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 63,
+ "records_with_pk": 63,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1,
+ "records_with_pk": 1,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11814,
+ "records_with_pk": 11814,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16080,
+ "records_with_pk": 16080,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2421,
+ "records_with_pk": 2421,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 6,
+ "records_with_pk": 6,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8226,
+ "records_with_pk": 8226,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052709671030981
+ },
+ {
+ "id": 3052709671014598
+ },
+ {
+ "id": 3052709671014597
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 262,
+ "records_with_pk": 262,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052703311204549
+ },
+ {
+ "sitegoodsstockid": 3052703310713029
+ },
+ {
+ "sitegoodsstockid": 3052703210262725
+ },
+ {
+ "sitegoodsstockid": 3052702889496709
+ }
+ ],
+ "pages": 3,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1640,
+ "records_with_pk": 1640,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 227,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 3,
+ "skipped_missing_pk": 227,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 7,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T22:39:29.785863+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_225414.json b/etl_billiards/reports/ods_gap_check_20260115_225414.json
new file mode 100644
index 0000000..7d6a168
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_225414.json
@@ -0,0 +1,434 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T22:41:52.530464+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21593,
+ "records_with_pk": 21593,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052709425844293
+ }
+ ],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9823,
+ "records_with_pk": 9823,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052709670179013
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4425,
+ "records_with_pk": 4425,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11816,
+ "records_with_pk": 11816,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052719648346117
+ },
+ {
+ "id": 3052709667573957
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16080,
+ "records_with_pk": 16080,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 551,
+ "records_with_pk": 551,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 936,
+ "records_with_pk": 936,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 800,
+ "records_with_pk": 800,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052719648968709
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/MemberProfile/GetMemberCardBalanceChange"
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 1,
+ "error_detail": "HTTPError: 502 Server Error: Bad Gateway for url: https://pc.ficoo.vip/apiprod/admin/v1/Site/GetFormerRechargeSettleList"
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8226,
+ "records_with_pk": 8226,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052709671030981
+ },
+ {
+ "id": 3052709671014598
+ },
+ {
+ "id": 3052709671014597
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28353,
+ "records_with_pk": 28353,
+ "missing": 6,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052711404949637
+ },
+ {
+ "sitegoodsstockid": 3052710332108805
+ },
+ {
+ "sitegoodsstockid": 3052703311204549
+ },
+ {
+ "sitegoodsstockid": 3052703310713029
+ },
+ {
+ "sitegoodsstockid": 3052703210262725
+ },
+ {
+ "sitegoodsstockid": 3052702889496709
+ }
+ ],
+ "pages": 287,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1640,
+ "records_with_pk": 1640,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22233,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22233,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 14,
+ "total_errors": 2,
+ "generated_at": "2026-01-15T22:54:14.091266+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_225543.json b/etl_billiards/reports/ods_gap_check_20260115_225543.json
new file mode 100644
index 0000000..a3ee564
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_225543.json
@@ -0,0 +1,57 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T22:54:43.572531+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2422,
+ "records_with_pk": 2422,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052719648968709
+ }
+ ],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 406,
+ "records_with_pk": 406,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 2832289312279685
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ }
+ ],
+ "total_missing": 2,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T22:55:43.243233+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_233027.json b/etl_billiards/reports/ods_gap_check_20260115_233027.json
new file mode 100644
index 0000000..296df01
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_233027.json
@@ -0,0 +1,486 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:17:27.865573+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21598,
+ "records_with_pk": 21598,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3052747511992453
+ },
+ {
+ "id": 3052735906484229
+ },
+ {
+ "id": 3052734153248901
+ },
+ {
+ "id": 3052731804225541
+ }
+ ],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9827,
+ "records_with_pk": 9827,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052747812589701
+ },
+ {
+ "id": 3052735966400645
+ },
+ {
+ "id": 3052734201450565
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052734201991237
+ },
+ {
+ "id": 3052719654719493
+ },
+ {
+ "id": 3052719654260741
+ }
+ ],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11821,
+ "records_with_pk": 11821,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052750319341573
+ },
+ {
+ "id": 3052747810050181
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16083,
+ "records_with_pk": 16083,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052741608968197
+ },
+ {
+ "id": 3052731064979526
+ },
+ {
+ "id": 3052731064979525
+ }
+ ],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052749341853317
+ }
+ ],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052750402162821
+ },
+ {
+ "id": 3052749343442565
+ }
+ ],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2426,
+ "records_with_pk": 2426,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052750769868677
+ },
+ {
+ "id": 3052750321078277
+ }
+ ],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 406,
+ "records_with_pk": 406,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8226,
+ "records_with_pk": 8226,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28362,
+ "records_with_pk": 28362,
+ "missing": 8,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052749480874181
+ },
+ {
+ "sitegoodsstockid": 3052746155790533
+ },
+ {
+ "sitegoodsstockid": 3052731830964357
+ },
+ {
+ "sitegoodsstockid": 3052731830816901
+ },
+ {
+ "sitegoodsstockid": 3052731610599429
+ },
+ {
+ "sitegoodsstockid": 3052731549978821
+ },
+ {
+ "sitegoodsstockid": 3052731205636229
+ },
+ {
+ "sitegoodsstockid": 3052731205144709
+ }
+ ],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1642,
+ "records_with_pk": 1642,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052735967137925
+ },
+ {
+ "id": 3052734202728517
+ }
+ ],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22238,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22238,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 30,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T23:30:27.730183+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_234709.json b/etl_billiards/reports/ods_gap_check_20260115_234709.json
new file mode 100644
index 0000000..3fe3b51
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_234709.json
@@ -0,0 +1,429 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39.434282+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765744894085
+ },
+ {
+ "id": 3052764742504453
+ }
+ ],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9829,
+ "records_with_pk": 9829,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765763162309
+ },
+ {
+ "id": 3052764761280581
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11823,
+ "records_with_pk": 11823,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765760803013
+ },
+ {
+ "id": 3052764758904901
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052771420229701
+ },
+ {
+ "id": 3052767969185925
+ }
+ ],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2426,
+ "records_with_pk": 2426,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052750316949509
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8228,
+ "records_with_pk": 8228,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765763981509
+ },
+ {
+ "id": 3052764762116165
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052765709897925
+ }
+ ],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1642,
+ "records_with_pk": 1642,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 12,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T23:47:09.386589+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260115_235955.json b/etl_billiards/reports/ods_gap_check_20260115_235955.json
new file mode 100644
index 0000000..72761ac
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260115_235955.json
@@ -0,0 +1,446 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765744894085
+ },
+ {
+ "id": 3052764742504453
+ }
+ ],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9830,
+ "records_with_pk": 9830,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052778957967493
+ },
+ {
+ "id": 3052765763162309
+ },
+ {
+ "id": 3052764761280581
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11824,
+ "records_with_pk": 11824,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052778953920645
+ },
+ {
+ "id": 3052765760803013
+ },
+ {
+ "id": 3052764758904901
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052771420229701
+ },
+ {
+ "id": 3052767969185925
+ }
+ ],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2428,
+ "records_with_pk": 2428,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052778954690693
+ },
+ {
+ "id": 3052778954494085
+ }
+ ],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052750316949509
+ }
+ ],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8228,
+ "records_with_pk": 8228,
+ "missing": 2,
+ "missing_samples": [
+ {
+ "id": 3052765763981509
+ },
+ {
+ "id": 3052764762116165
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "sitegoodsstockid": 3052765709897925
+ }
+ ],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1643,
+ "records_with_pk": 1643,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052778959048837
+ }
+ ],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 17,
+ "total_errors": 0,
+ "generated_at": "2026-01-15T23:59:55.963574+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260116_001716.json b/etl_billiards/reports/ods_gap_check_20260116_001716.json
new file mode 100644
index 0000000..93785f7
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260116_001716.json
@@ -0,0 +1,394 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9831,
+ "records_with_pk": 9831,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11826,
+ "records_with_pk": 11826,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052800806752261
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2428,
+ "records_with_pk": 2428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8229,
+ "records_with_pk": 8229,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052800809783301
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1644,
+ "records_with_pk": 1644,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 2,
+ "total_errors": 0,
+ "generated_at": "2026-01-16T00:17:16.884691+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260116_003620.json b/etl_billiards/reports/ods_gap_check_20260116_003620.json
new file mode 100644
index 0000000..a86c884
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260116_003620.json
@@ -0,0 +1,390 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9832,
+ "records_with_pk": 9832,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052800809242629
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11826,
+ "records_with_pk": 11826,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2428,
+ "records_with_pk": 2428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8229,
+ "records_with_pk": 8229,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1644,
+ "records_with_pk": 1644,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 1,
+ "total_errors": 0,
+ "generated_at": "2026-01-16T00:36:20.647772+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260116_005452.json b/etl_billiards/reports/ods_gap_check_20260116_005452.json
new file mode 100644
index 0000000..f731105
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260116_005452.json
@@ -0,0 +1,426 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9837,
+ "records_with_pk": 9837,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3052832498323653
+ },
+ {
+ "id": 3052831407345733
+ },
+ {
+ "id": 3052831407362117
+ },
+ {
+ "id": 3052830659924037
+ }
+ ],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11830,
+ "records_with_pk": 11830,
+ "missing": 4,
+ "missing_samples": [
+ {
+ "id": 3052832495997125
+ },
+ {
+ "id": 3052831403331653
+ },
+ {
+ "id": 3052830657482821
+ },
+ {
+ "id": 3052823016361989
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2428,
+ "records_with_pk": 2428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8232,
+ "records_with_pk": 8232,
+ "missing": 3,
+ "missing_samples": [
+ {
+ "id": 3052832498929862
+ },
+ {
+ "id": 3052832498929861
+ },
+ {
+ "id": 3052830660579397
+ }
+ ],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1645,
+ "records_with_pk": 1645,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052831408820293
+ }
+ ],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 12,
+ "total_errors": 0,
+ "generated_at": "2026-01-16T00:54:52.208868+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_20260116_020724.json b/etl_billiards/reports/ods_gap_check_20260116_020724.json
new file mode 100644
index 0000000..2ee182a
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_20260116_020724.json
@@ -0,0 +1,394 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-15T23:34:39+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 100,
+ "chunk_size": 200,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_ASSISTANT_ACCOUNT",
+ "table": "billiards_ods.assistant_accounts_master",
+ "endpoint": "/PersonnelManagement/SearchAssistantInfo",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 448,
+ "records_with_pk": 448,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_RECORDS",
+ "table": "billiards_ods.settlement_records",
+ "endpoint": "/Site/GetAllOrderSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 21600,
+ "records_with_pk": 21600,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 221,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9841,
+ "records_with_pk": 9841,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 99,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_LEDGER",
+ "table": "billiards_ods.assistant_service_records",
+ "endpoint": "/AssistantPerformance/GetOrderAssistantDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 4428,
+ "records_with_pk": 4428,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 48,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_ASSISTANT_ABOLISH",
+ "table": "billiards_ods.assistant_cancellation_records",
+ "endpoint": "/AssistantPerformance/GetAbolitionAssistant",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 79,
+ "records_with_pk": 79,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 7,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS_SALES",
+ "table": "billiards_ods.store_goods_sales_records",
+ "endpoint": "/TenantGoods/GetGoodsSalesList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11835,
+ "records_with_pk": 11835,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052908806459589
+ }
+ ],
+ "pages": 119,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_REFUND",
+ "table": "billiards_ods.refund_transactions",
+ "endpoint": "/Order/GetRefundPayLogList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 36,
+ "records_with_pk": 36,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PLATFORM_COUPON",
+ "table": "billiards_ods.platform_coupon_redemption_records",
+ "endpoint": "/Promotion/GetOfflineCouponConsumePageList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 16086,
+ "records_with_pk": 16086,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 161,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER",
+ "table": "billiards_ods.member_profiles",
+ "endpoint": "/MemberProfile/GetTenantMemberList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 552,
+ "records_with_pk": 552,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 6,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_CARD",
+ "table": "billiards_ods.member_stored_value_cards",
+ "endpoint": "/MemberProfile/GetTenantMemberCardList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 938,
+ "records_with_pk": 938,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 10,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_MEMBER_BALANCE",
+ "table": "billiards_ods.member_balance_changes",
+ "endpoint": "/MemberProfile/GetMemberCardBalanceChange",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 2429,
+ "records_with_pk": 2429,
+ "missing": 1,
+ "missing_samples": [
+ {
+ "id": 3052862467248261
+ }
+ ],
+ "pages": 25,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_RECHARGE_SETTLE",
+ "table": "billiards_ods.recharge_settlements",
+ "endpoint": "/Site/GetRechargeSettleList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 407,
+ "records_with_pk": 407,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 8,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_PACKAGE",
+ "table": "billiards_ods.group_buy_packages",
+ "endpoint": "/PackageCoupon/QueryPackageCouponList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 18,
+ "records_with_pk": 18,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8234,
+ "records_with_pk": 8234,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 83,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_STOCK",
+ "table": "billiards_ods.goods_stock_summary",
+ "endpoint": "/TenantGoods/GetGoodsStockReport",
+ "pk_columns": [
+ "sitegoodsid"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_INVENTORY_CHANGE",
+ "table": "billiards_ods.goods_stock_movements",
+ "endpoint": "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "pk_columns": [
+ "sitegoodsstockid"
+ ],
+ "records": 28364,
+ "records_with_pk": 28364,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 288,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLES",
+ "table": "billiards_ods.site_tables_master",
+ "endpoint": "/Table/GetSiteTables",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 74,
+ "records_with_pk": 74,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GOODS_CATEGORY",
+ "table": "billiards_ods.stock_goods_category_tree",
+ "endpoint": "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9,
+ "records_with_pk": 9,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 1,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_STORE_GOODS",
+ "table": "billiards_ods.store_goods_master",
+ "endpoint": "/TenantGoods/GetGoodsInventoryList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 169,
+ "records_with_pk": 169,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1646,
+ "records_with_pk": 1646,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 17,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TENANT_GOODS",
+ "table": "billiards_ods.tenant_goods_master",
+ "endpoint": "/TenantGoods/QueryTenantGoods",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 170,
+ "records_with_pk": 170,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 2,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": "billiards_ods.settlement_ticket_details",
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": [
+ "ordersettleid"
+ ],
+ "records": 22241,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 226,
+ "skipped_missing_pk": 22241,
+ "errors": 0,
+ "error_detail": null,
+ "source_endpoint": "/PayLog/GetPayLogListPage"
+ }
+ ],
+ "total_missing": 2,
+ "total_errors": 0,
+ "generated_at": "2026-01-16T02:07:24.368217+08:00"
+}
diff --git a/etl_billiards/reports/ods_gap_check_after_fill_20260116_024030.json b/etl_billiards/reports/ods_gap_check_after_fill_20260116_024030.json
new file mode 100644
index 0000000..39908c6
--- /dev/null
+++ b/etl_billiards/reports/ods_gap_check_after_fill_20260116_024030.json
@@ -0,0 +1,81 @@
+{
+ "start": "2025-07-01T00:00:00+08:00",
+ "end": "2026-01-16T02:39:19.009379+08:00",
+ "cutoff": null,
+ "window_days": 30,
+ "window_hours": 0,
+ "page_size": 200,
+ "chunk_size": 500,
+ "sample_limit": 50,
+ "store_id": 2790685415443269,
+ "base_url": "https://pc.ficoo.vip/apiprod/admin/v1/",
+ "results": [
+ {
+ "task_code": "ODS_TABLE_USE",
+ "table": "billiards_ods.table_fee_transactions",
+ "endpoint": "/Site/GetSiteTableOrderDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 9842,
+ "records_with_pk": 9842,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 50,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_PAYMENT",
+ "table": "billiards_ods.payment_transactions",
+ "endpoint": "/PayLog/GetPayLogListPage",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 11836,
+ "records_with_pk": 11836,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 60,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_GROUP_BUY_REDEMPTION",
+ "table": "billiards_ods.group_buy_redemption_records",
+ "endpoint": "/Site/GetSiteTableUseDetails",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 8234,
+ "records_with_pk": 8234,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 42,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ },
+ {
+ "task_code": "ODS_TABLE_FEE_DISCOUNT",
+ "table": "billiards_ods.table_fee_discount_records",
+ "endpoint": "/Site/GetTaiFeeAdjustList",
+ "pk_columns": [
+ "id"
+ ],
+ "records": 1646,
+ "records_with_pk": 1646,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 9,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": null
+ }
+ ],
+ "total_missing": 0,
+ "total_errors": 0,
+ "generated_at": "2026-01-16T02:40:30.650075+08:00"
+}
diff --git a/etl_billiards/requirements.txt b/etl_billiards/requirements.txt
index 42c8889..2470799 100644
--- a/etl_billiards/requirements.txt
+++ b/etl_billiards/requirements.txt
@@ -3,3 +3,10 @@ psycopg2-binary>=2.9.0
requests>=2.28.0
python-dateutil>=2.8.0
tzdata>=2023.0
+flask>=2.3
+
+# GUI 依赖
+PySide6>=6.5.0
+
+# 打包工具 (可选,仅打包 EXE 时需要)
+# pyinstaller>=6.0.0
diff --git a/etl_billiards/run_gui.bat b/etl_billiards/run_gui.bat
new file mode 100644
index 0000000..f3fc6ab
--- /dev/null
+++ b/etl_billiards/run_gui.bat
@@ -0,0 +1,27 @@
+@echo off
+chcp 65001 >nul
+cd /d "%~dp0"
+
+echo ====================================
+echo 飞球 ETL 管理系统
+echo ====================================
+echo.
+
+REM 检查 Python
+python --version >nul 2>&1
+if errorlevel 1 (
+ echo [错误] 未找到 Python,请先安装 Python 3.10+
+ pause
+ exit /b 1
+)
+
+REM 启动 GUI
+echo 正在启动 GUI...
+python -m gui.main
+
+if errorlevel 1 (
+ echo.
+ echo [错误] 启动失败,请检查依赖是否已安装
+ echo 运行: pip install -r requirements.txt
+ pause
+)
diff --git a/etl_billiards/run_gui.ps1 b/etl_billiards/run_gui.ps1
new file mode 100644
index 0000000..0359234
--- /dev/null
+++ b/etl_billiards/run_gui.ps1
@@ -0,0 +1,42 @@
+# PowerShell 启动脚本
+# 飞球 ETL 管理系统
+
+$ErrorActionPreference = "Stop"
+$OutputEncoding = [System.Text.Encoding]::UTF8
+
+Write-Host "===================================="
+Write-Host " 飞球 ETL 管理系统"
+Write-Host "===================================="
+Write-Host ""
+
+# 切换到脚本目录
+Set-Location $PSScriptRoot
+
+# 检查 Python
+try {
+ $pythonVersion = python --version 2>&1
+ Write-Host "Python 版本: $pythonVersion"
+} catch {
+ Write-Host "[错误] 未找到 Python,请先安装 Python 3.10+" -ForegroundColor Red
+ Read-Host "按回车键退出"
+ exit 1
+}
+
+# 检查 PySide6
+$hasPySide6 = python -c "import PySide6" 2>&1
+if ($LASTEXITCODE -ne 0) {
+ Write-Host "[提示] 正在安装 GUI 依赖..." -ForegroundColor Yellow
+ pip install PySide6
+}
+
+# 启动 GUI
+Write-Host ""
+Write-Host "正在启动 GUI..." -ForegroundColor Cyan
+python -m gui.main
+
+if ($LASTEXITCODE -ne 0) {
+ Write-Host ""
+ Write-Host "[错误] 启动失败" -ForegroundColor Red
+ Write-Host "请运行: pip install -r requirements.txt"
+ Read-Host "按回车键退出"
+}
diff --git a/etl_billiards/run_ods.bat b/etl_billiards/run_ods.bat
new file mode 100644
index 0000000..023d10d
--- /dev/null
+++ b/etl_billiards/run_ods.bat
@@ -0,0 +1,27 @@
+@echo off
+REM -*- coding: utf-8 -*-
+REM 说明:一键重建 ODS(执行 INIT_ODS_SCHEMA)并灌入示例 JSON(执行 MANUAL_INGEST)
+REM 使用配置:.env 中 PG_DSN、INGEST_SOURCE_DIR,或通过参数覆盖
+
+setlocal
+cd /d %~dp0
+
+REM 如果需要覆盖示例目录,可修改下面的 INGEST_DIR
+set "INGEST_DIR=export\\test-json-doc"
+
+echo [INIT_ODS_SCHEMA] 准备执行,源目录=%INGEST_DIR%
+python -m cli.main --tasks INIT_ODS_SCHEMA --pipeline-flow INGEST_ONLY --ingest-source "%INGEST_DIR%"
+if errorlevel 1 (
+ echo INIT_ODS_SCHEMA 失败,退出
+ exit /b 1
+)
+
+echo [MANUAL_INGEST] 准备执行,源目录=%INGEST_DIR%
+python -m cli.main --tasks MANUAL_INGEST --pipeline-flow INGEST_ONLY --ingest-source "%INGEST_DIR%"
+if errorlevel 1 (
+ echo MANUAL_INGEST 失败,退出
+ exit /b 1
+)
+
+echo 全部完成。
+endlocal
diff --git a/etl_billiards/run_update.py b/etl_billiards/run_update.py
new file mode 100644
index 0000000..9cfa6f3
--- /dev/null
+++ b/etl_billiards/run_update.py
@@ -0,0 +1,517 @@
+# -*- coding: utf-8 -*-
+"""
+一键增量更新脚本(ODS -> DWD -> DWS)。
+
+用法:
+ cd etl_billiards
+ python run_update.py
+"""
+
+from __future__ import annotations
+
+import argparse
+import logging
+import multiprocessing as mp
+import subprocess
+import sys
+import time as time_mod
+from datetime import date, datetime, time, timedelta
+from pathlib import Path
+from zoneinfo import ZoneInfo
+
+from api.client import APIClient
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+from database.operations import DatabaseOperations
+from orchestration.scheduler import ETLScheduler
+from tasks.check_cutoff_task import CheckCutoffTask
+from tasks.dwd_load_task import DwdLoadTask
+from tasks.ods_tasks import ENABLED_ODS_CODES
+from utils.logging_utils import build_log_path, configure_logging
+
+STEP_TIMEOUT_SEC = 120
+
+
+
+def _coerce_date(s: str) -> date:
+ s = (s or "").strip()
+ if not s:
+ raise ValueError("empty date")
+ if len(s) >= 10:
+ s = s[:10]
+ return date.fromisoformat(s)
+
+
+def _compute_dws_window(
+ *,
+ cfg: AppConfig,
+ tz: ZoneInfo,
+ rebuild_days: int,
+ bootstrap_days: int,
+ dws_start: date | None,
+ dws_end: date | None,
+) -> tuple[datetime, datetime]:
+ if dws_start and dws_end and dws_end < dws_start:
+ raise ValueError("dws_end must be >= dws_start")
+
+ store_id = int(cfg.get("app.store_id"))
+ dsn = cfg["db"]["dsn"]
+ session = cfg["db"].get("session")
+ conn = DatabaseConnection(dsn=dsn, session=session)
+ try:
+ if dws_start is None:
+ row = conn.query(
+ "SELECT MAX(order_date) AS mx FROM billiards_dws.dws_order_summary WHERE site_id=%s",
+ (store_id,),
+ )
+ mx = (row[0] or {}).get("mx") if row else None
+ if isinstance(mx, date):
+ dws_start = mx - timedelta(days=max(0, int(rebuild_days)))
+ else:
+ dws_start = (datetime.now(tz).date()) - timedelta(days=max(1, int(bootstrap_days)))
+
+ if dws_end is None:
+ dws_end = datetime.now(tz).date()
+ finally:
+ conn.close()
+
+ start_dt = datetime.combine(dws_start, time.min).replace(tzinfo=tz)
+ # end_dt 取到当天 23:59:59,避免只跑到“当前时刻”的 date() 导致少一天
+ end_dt = datetime.combine(dws_end, time.max).replace(tzinfo=tz)
+ return start_dt, end_dt
+
+
+def _run_check_cutoff(cfg: AppConfig, logger: logging.Logger):
+ dsn = cfg["db"]["dsn"]
+ session = cfg["db"].get("session")
+ db_conn = DatabaseConnection(dsn=dsn, session=session)
+ db_ops = DatabaseOperations(db_conn)
+ api = APIClient(
+ base_url=cfg["api"]["base_url"],
+ token=cfg["api"]["token"],
+ timeout=cfg["api"]["timeout_sec"],
+ retry_max=cfg["api"]["retries"]["max_attempts"],
+ headers_extra=cfg["api"].get("headers_extra"),
+ )
+ try:
+ CheckCutoffTask(cfg, db_ops, api, logger).execute(None)
+ finally:
+ db_conn.close()
+
+
+def _iter_daily_windows(window_start: datetime, window_end: datetime) -> list[tuple[datetime, datetime]]:
+ if window_start > window_end:
+ return []
+ tz = window_start.tzinfo
+ windows: list[tuple[datetime, datetime]] = []
+ cur = window_start
+ while cur <= window_end:
+ day_start = datetime.combine(cur.date(), time.min).replace(tzinfo=tz)
+ day_end = datetime.combine(cur.date(), time.max).replace(tzinfo=tz)
+ if day_start < window_start:
+ day_start = window_start
+ if day_end > window_end:
+ day_end = window_end
+ windows.append((day_start, day_end))
+ next_day = cur.date() + timedelta(days=1)
+ cur = datetime.combine(next_day, time.min).replace(tzinfo=tz)
+ return windows
+
+
+def _run_step_worker(result_queue: "mp.Queue[dict[str, str]]", step: dict[str, str]) -> None:
+ if hasattr(sys.stdout, "reconfigure"):
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+ log_file = step.get("log_file") or ""
+ log_level = step.get("log_level") or "INFO"
+ log_console = bool(step.get("log_console", True))
+ log_path = Path(log_file) if log_file else None
+
+ with configure_logging(
+ "etl_update",
+ log_path,
+ level=log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg_base = AppConfig.load({})
+ step_type = step.get("type", "")
+ try:
+ if step_type == "check_cutoff":
+ _run_check_cutoff(cfg_base, logger)
+ elif step_type == "ods_task":
+ task_code = step["task_code"]
+ overlap_seconds = int(step.get("overlap_seconds", 0))
+ cfg_ods = AppConfig.load(
+ {
+ "pipeline": {"flow": "FULL"},
+ "run": {"tasks": [task_code], "overlap_seconds": overlap_seconds},
+ }
+ )
+ scheduler = ETLScheduler(cfg_ods, logger)
+ try:
+ scheduler.run_tasks([task_code])
+ finally:
+ scheduler.close()
+ elif step_type == "init_dws_schema":
+ overlap_seconds = int(step.get("overlap_seconds", 0))
+ cfg_dwd = AppConfig.load(
+ {
+ "pipeline": {"flow": "INGEST_ONLY"},
+ "run": {"tasks": ["INIT_DWS_SCHEMA"], "overlap_seconds": overlap_seconds},
+ }
+ )
+ scheduler = ETLScheduler(cfg_dwd, logger)
+ try:
+ scheduler.run_tasks(["INIT_DWS_SCHEMA"])
+ finally:
+ scheduler.close()
+ elif step_type == "dwd_table":
+ dwd_table = step["dwd_table"]
+ overlap_seconds = int(step.get("overlap_seconds", 0))
+ cfg_dwd = AppConfig.load(
+ {
+ "pipeline": {"flow": "INGEST_ONLY"},
+ "run": {"tasks": ["DWD_LOAD_FROM_ODS"], "overlap_seconds": overlap_seconds},
+ "dwd": {"only_tables": [dwd_table]},
+ }
+ )
+ scheduler = ETLScheduler(cfg_dwd, logger)
+ try:
+ scheduler.run_tasks(["DWD_LOAD_FROM_ODS"])
+ finally:
+ scheduler.close()
+ elif step_type == "dws_window":
+ overlap_seconds = int(step.get("overlap_seconds", 0))
+ window_start = step["window_start"]
+ window_end = step["window_end"]
+ cfg_dws = AppConfig.load(
+ {
+ "pipeline": {"flow": "INGEST_ONLY"},
+ "run": {
+ "tasks": ["DWS_BUILD_ORDER_SUMMARY"],
+ "overlap_seconds": overlap_seconds,
+ "window_override": {"start": window_start, "end": window_end},
+ },
+ }
+ )
+ scheduler = ETLScheduler(cfg_dws, logger)
+ try:
+ scheduler.run_tasks(["DWS_BUILD_ORDER_SUMMARY"])
+ finally:
+ scheduler.close()
+ elif step_type == "ods_gap_check":
+ overlap_hours = int(step.get("overlap_hours", 24))
+ window_days = int(step.get("window_days", 1))
+ window_hours = int(step.get("window_hours", 0))
+ page_size = int(step.get("page_size", 0) or 0)
+ sleep_per_window = float(step.get("sleep_per_window", 0) or 0)
+ sleep_per_page = float(step.get("sleep_per_page", 0) or 0)
+ tag = step.get("tag", "run_update")
+ task_codes = (step.get("task_codes") or "").strip()
+ script_dir = Path(__file__).resolve().parent
+ script_path = script_dir / "scripts" / "check_ods_gaps.py"
+ cmd = [
+ sys.executable,
+ str(script_path),
+ "--from-cutoff",
+ "--cutoff-overlap-hours",
+ str(overlap_hours),
+ "--window-days",
+ str(window_days),
+ "--tag",
+ str(tag),
+ ]
+ if window_hours > 0:
+ cmd += ["--window-hours", str(window_hours)]
+ if page_size > 0:
+ cmd += ["--page-size", str(page_size)]
+ if sleep_per_window > 0:
+ cmd += ["--sleep-per-window-seconds", str(sleep_per_window)]
+ if sleep_per_page > 0:
+ cmd += ["--sleep-per-page-seconds", str(sleep_per_page)]
+ if task_codes:
+ cmd += ["--task-codes", task_codes]
+ subprocess.run(cmd, check=True, cwd=str(script_dir))
+ else:
+ raise ValueError(f"Unknown step type: {step_type}")
+ result_queue.put({"status": "ok"})
+ except Exception as exc:
+ result_queue.put({"status": "error", "error": str(exc)})
+
+
+def _run_step_with_timeout(
+ step: dict[str, str], logger: logging.Logger, timeout_sec: int
+) -> dict[str, object]:
+ start = time_mod.monotonic()
+ step_timeout = timeout_sec
+ if step.get("timeout_sec"):
+ try:
+ step_timeout = int(step.get("timeout_sec"))
+ except Exception:
+ step_timeout = timeout_sec
+ ctx = mp.get_context("spawn")
+ result_queue: mp.Queue = ctx.Queue()
+ proc = ctx.Process(target=_run_step_worker, args=(result_queue, step))
+ proc.start()
+ proc.join(timeout=step_timeout)
+ elapsed = time_mod.monotonic() - start
+ if proc.is_alive():
+ logger.error(
+ "STEP_TIMEOUT name=%s elapsed=%.2fs limit=%ss", step["name"], elapsed, step_timeout
+ )
+ proc.terminate()
+ proc.join(10)
+ return {"name": step["name"], "status": "timeout", "elapsed": elapsed}
+
+ result: dict[str, object] = {"name": step["name"], "status": "error", "elapsed": elapsed}
+ try:
+ payload = result_queue.get_nowait()
+ except Exception:
+ payload = {}
+ if payload:
+ result.update(payload)
+
+ if result.get("status") == "ok":
+ logger.info("STEP_OK name=%s elapsed=%.2fs", step["name"], elapsed)
+ else:
+ logger.error(
+ "STEP_FAIL name=%s elapsed=%.2fs error=%s",
+ step["name"],
+ elapsed,
+ result.get("error"),
+ )
+ return result
+
+
+def main() -> int:
+ if hasattr(sys.stdout, "reconfigure"):
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+
+ parser = argparse.ArgumentParser(description="One-click ETL update (ODS -> DWD -> DWS)")
+ parser.add_argument("--overlap-seconds", type=int, default=3600, help="overlap seconds (default: 3600)")
+ parser.add_argument(
+ "--dws-rebuild-days",
+ type=int,
+ default=1,
+ help="DWS 回算冗余天数(default: 1)",
+ )
+ parser.add_argument(
+ "--dws-bootstrap-days",
+ type=int,
+ default=30,
+ help="DWS 首次/空表时回算天数(default: 30)",
+ )
+ parser.add_argument("--dws-start", type=str, default="", help="DWS 回算开始日期 YYYY-MM-DD(可选)")
+ parser.add_argument("--dws-end", type=str, default="", help="DWS 回算结束日期 YYYY-MM-DD(可选)")
+ parser.add_argument(
+ "--skip-cutoff",
+ action="store_true",
+ help="跳过 CHECK_CUTOFF(默认会在开始/结束各跑一次)",
+ )
+ parser.add_argument(
+ "--skip-ods",
+ action="store_true",
+ help="跳过 ODS 在线抓取(仅跑 DWD/DWS)",
+ )
+ parser.add_argument(
+ "--ods-tasks",
+ type=str,
+ default="",
+ help="指定要跑的 ODS 任务(逗号分隔),默认跑全部 ENABLED_ODS_CODES",
+ )
+ parser.add_argument(
+ "--check-ods-gaps",
+ action="store_true",
+ help="run ODS gap check after ODS load (default: off)",
+ )
+ parser.add_argument(
+ "--check-ods-overlap-hours",
+ type=int,
+ default=24,
+ help="gap check overlap hours from cutoff (default: 24)",
+ )
+ parser.add_argument(
+ "--check-ods-window-days",
+ type=int,
+ default=1,
+ help="gap check window days (default: 1)",
+ )
+ parser.add_argument(
+ "--check-ods-window-hours",
+ type=int,
+ default=0,
+ help="gap check window hours (default: 0)",
+ )
+ parser.add_argument(
+ "--check-ods-page-size",
+ type=int,
+ default=200,
+ help="gap check API page size (default: 200)",
+ )
+ parser.add_argument(
+ "--check-ods-timeout-sec",
+ type=int,
+ default=1800,
+ help="gap check timeout seconds (default: 1800)",
+ )
+ parser.add_argument(
+ "--check-ods-task-codes",
+ type=str,
+ default="",
+ help="gap check task codes (comma-separated, optional)",
+ )
+ parser.add_argument(
+ "--check-ods-sleep-per-window-seconds",
+ type=float,
+ default=0,
+ help="gap check sleep seconds after each window (default: 0)",
+ )
+ parser.add_argument(
+ "--check-ods-sleep-per-page-seconds",
+ type=float,
+ default=0,
+ help="gap check sleep seconds after each page (default: 0)",
+ )
+ parser.add_argument("--log-file", type=str, default="", help="log file path (default: logs/run_update_YYYYMMDD_HHMMSS.log)")
+ parser.add_argument("--log-dir", type=str, default="", help="log directory (default: logs)")
+ parser.add_argument("--log-level", type=str, default="INFO", help="log level (default: INFO)")
+ parser.add_argument("--no-log-console", action="store_true", help="disable console logging")
+ args = parser.parse_args()
+
+ log_dir = Path(args.log_dir) if args.log_dir else (Path(__file__).resolve().parent / "logs")
+ log_file = Path(args.log_file) if args.log_file else build_log_path(log_dir, "run_update")
+ log_console = not args.no_log_console
+
+ with configure_logging(
+ "etl_update",
+ log_file,
+ level=args.log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg_base = AppConfig.load({})
+ tz = ZoneInfo(cfg_base.get("app.timezone", "Asia/Taipei"))
+
+ dws_start = _coerce_date(args.dws_start) if args.dws_start else None
+ dws_end = _coerce_date(args.dws_end) if args.dws_end else None
+
+ steps: list[dict[str, str]] = []
+ if not args.skip_cutoff:
+ steps.append({"name": "CHECK_CUTOFF:before", "type": "check_cutoff"})
+
+ # ------------------------------------------------------------------ ODS (online fetch + load)
+ if not args.skip_ods:
+ if args.ods_tasks:
+ ods_tasks = [t.strip().upper() for t in args.ods_tasks.split(",") if t.strip()]
+ else:
+ ods_tasks = sorted(ENABLED_ODS_CODES)
+ for task_code in ods_tasks:
+ steps.append(
+ {
+ "name": f"ODS:{task_code}",
+ "type": "ods_task",
+ "task_code": task_code,
+ "overlap_seconds": str(args.overlap_seconds),
+ }
+ )
+
+ if args.check_ods_gaps:
+ steps.append(
+ {
+ "name": "ODS_GAP_CHECK",
+ "type": "ods_gap_check",
+ "overlap_hours": str(args.check_ods_overlap_hours),
+ "window_days": str(args.check_ods_window_days),
+ "window_hours": str(args.check_ods_window_hours),
+ "page_size": str(args.check_ods_page_size),
+ "sleep_per_window": str(args.check_ods_sleep_per_window_seconds),
+ "sleep_per_page": str(args.check_ods_sleep_per_page_seconds),
+ "timeout_sec": str(args.check_ods_timeout_sec),
+ "task_codes": str(args.check_ods_task_codes or ""),
+ "tag": "run_update",
+ }
+ )
+
+ # ------------------------------------------------------------------ DWD (load from ODS tables)
+ steps.append(
+ {
+ "name": "INIT_DWS_SCHEMA",
+ "type": "init_dws_schema",
+ "overlap_seconds": str(args.overlap_seconds),
+ }
+ )
+ for dwd_table in DwdLoadTask.TABLE_MAP.keys():
+ steps.append(
+ {
+ "name": f"DWD:{dwd_table}",
+ "type": "dwd_table",
+ "dwd_table": dwd_table,
+ "overlap_seconds": str(args.overlap_seconds),
+ }
+ )
+
+ # ------------------------------------------------------------------ DWS (rebuild by date window)
+ window_start, window_end = _compute_dws_window(
+ cfg=cfg_base,
+ tz=tz,
+ rebuild_days=int(args.dws_rebuild_days),
+ bootstrap_days=int(args.dws_bootstrap_days),
+ dws_start=dws_start,
+ dws_end=dws_end,
+ )
+ for start_dt, end_dt in _iter_daily_windows(window_start, window_end):
+ steps.append(
+ {
+ "name": f"DWS:{start_dt.date().isoformat()}",
+ "type": "dws_window",
+ "window_start": start_dt.strftime("%Y-%m-%d %H:%M:%S"),
+ "window_end": end_dt.strftime("%Y-%m-%d %H:%M:%S"),
+ "overlap_seconds": str(args.overlap_seconds),
+ }
+ )
+
+ if not args.skip_cutoff:
+ steps.append({"name": "CHECK_CUTOFF:after", "type": "check_cutoff"})
+
+ for step in steps:
+ step["log_file"] = str(log_file)
+ step["log_level"] = args.log_level
+ step["log_console"] = log_console
+
+ step_results: list[dict[str, object]] = []
+ for step in steps:
+ logger.info("STEP_START name=%s timeout=%ss", step["name"], STEP_TIMEOUT_SEC)
+ result = _run_step_with_timeout(step, logger, STEP_TIMEOUT_SEC)
+ step_results.append(result)
+
+ total = len(step_results)
+ ok_count = sum(1 for r in step_results if r.get("status") == "ok")
+ timeout_count = sum(1 for r in step_results if r.get("status") == "timeout")
+ fail_count = total - ok_count - timeout_count
+ logger.info(
+ "STEP_SUMMARY total=%s ok=%s failed=%s timeout=%s",
+ total,
+ ok_count,
+ fail_count,
+ timeout_count,
+ )
+ for item in sorted(step_results, key=lambda r: float(r.get("elapsed", 0.0)), reverse=True):
+ logger.info(
+ "STEP_RESULT name=%s status=%s elapsed=%.2fs",
+ item.get("name"),
+ item.get("status"),
+ item.get("elapsed", 0.0),
+ )
+
+ logger.info("Update done.")
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/Temp1.py b/etl_billiards/scripts/Temp1.py
deleted file mode 100644
index e69de29..0000000
diff --git a/etl_billiards/scripts/__init__.py b/etl_billiards/scripts/__init__.py
new file mode 100644
index 0000000..4484fd2
--- /dev/null
+++ b/etl_billiards/scripts/__init__.py
@@ -0,0 +1 @@
+# Script helpers package marker.
diff --git a/etl_billiards/scripts/backfill_missing_data.py b/etl_billiards/scripts/backfill_missing_data.py
new file mode 100644
index 0000000..cdc60c5
--- /dev/null
+++ b/etl_billiards/scripts/backfill_missing_data.py
@@ -0,0 +1,684 @@
+# -*- coding: utf-8 -*-
+"""
+补全丢失的 ODS 数据
+
+通过运行数据完整性检查,找出 API 与 ODS 之间的差异,
+然后重新从 API 获取丢失的数据并插入 ODS。
+
+用法:
+ python -m scripts.backfill_missing_data --start 2025-07-01 --end 2026-01-19
+ python -m scripts.backfill_missing_data --from-report reports/ods_gap_check_xxx.json
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import logging
+import sys
+import time as time_mod
+from datetime import datetime, timedelta
+from pathlib import Path
+from typing import Any, Dict, List, Optional, Set, Tuple
+from zoneinfo import ZoneInfo
+
+from dateutil import parser as dtparser
+from psycopg2.extras import Json, execute_values
+
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from api.client import APIClient
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+from models.parsers import TypeParser
+from tasks.ods_tasks import ENABLED_ODS_CODES, ODS_TASK_SPECS, OdsTaskSpec
+from scripts.check_ods_gaps import run_gap_check
+from utils.logging_utils import build_log_path, configure_logging
+
+
+def _reconfigure_stdout_utf8() -> None:
+ if hasattr(sys.stdout, "reconfigure"):
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+
+
+def _parse_dt(value: str, tz: ZoneInfo, *, is_end: bool = False) -> datetime:
+ raw = (value or "").strip()
+ if not raw:
+ raise ValueError("empty datetime")
+ has_time = any(ch in raw for ch in (":", "T"))
+ dt = dtparser.parse(raw)
+ if dt.tzinfo is None:
+ dt = dt.replace(tzinfo=tz)
+ else:
+ dt = dt.astimezone(tz)
+ if not has_time:
+ dt = dt.replace(
+ hour=23 if is_end else 0,
+ minute=59 if is_end else 0,
+ second=59 if is_end else 0,
+ microsecond=0
+ )
+ return dt
+
+
+def _get_spec(code: str) -> Optional[OdsTaskSpec]:
+ """根据任务代码获取 ODS 任务规格"""
+ for spec in ODS_TASK_SPECS:
+ if spec.code == code:
+ return spec
+ return None
+
+
+def _merge_record_layers(record: dict) -> dict:
+ """展开嵌套的 data 层"""
+ merged = record
+ data_part = merged.get("data")
+ while isinstance(data_part, dict):
+ merged = {**data_part, **merged}
+ data_part = data_part.get("data")
+ settle_inner = merged.get("settleList")
+ if isinstance(settle_inner, dict):
+ merged = {**settle_inner, **merged}
+ return merged
+
+
+def _get_value_case_insensitive(record: dict | None, col: str | None):
+ """不区分大小写地获取值"""
+ if record is None or col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+
+def _normalize_pk_value(value):
+ """规范化 PK 值"""
+ if value is None:
+ return None
+ if isinstance(value, str) and value.isdigit():
+ try:
+ return int(value)
+ except Exception:
+ return value
+ return value
+
+
+def _pk_tuple_from_record(record: dict, pk_cols: List[str]) -> Optional[Tuple]:
+ """从记录中提取 PK 元组"""
+ merged = _merge_record_layers(record)
+ values = []
+ for col in pk_cols:
+ val = _normalize_pk_value(_get_value_case_insensitive(merged, col))
+ if val is None or val == "":
+ return None
+ values.append(val)
+ return tuple(values)
+
+
+def _get_table_pk_columns(conn, table: str) -> List[str]:
+ """获取表的主键列"""
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT kcu.column_name
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.constraint_name = kcu.constraint_name
+ AND tc.table_schema = kcu.table_schema
+ WHERE tc.constraint_type = 'PRIMARY KEY'
+ AND tc.table_schema = %s
+ AND tc.table_name = %s
+ ORDER BY kcu.ordinal_position
+ """
+ with conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ return [r[0] for r in cur.fetchall()]
+
+
+def _get_table_columns(conn, table: str) -> List[Tuple[str, str, str]]:
+ """获取表的所有列信息"""
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT column_name, data_type, udt_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """
+ with conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ return [(r[0], (r[1] or "").lower(), (r[2] or "").lower()) for r in cur.fetchall()]
+
+
+def _fetch_existing_pk_set(
+ conn, table: str, pk_cols: List[str], pk_values: List[Tuple], chunk_size: int
+) -> Set[Tuple]:
+ """获取已存在的 PK 集合"""
+ if not pk_values:
+ return set()
+ select_cols = ", ".join(f't."{c}"' for c in pk_cols)
+ value_cols = ", ".join(f'"{c}"' for c in pk_cols)
+ join_cond = " AND ".join(f't."{c}" = v."{c}"' for c in pk_cols)
+ sql = (
+ f"SELECT {select_cols} FROM {table} t "
+ f"JOIN (VALUES %s) AS v({value_cols}) ON {join_cond}"
+ )
+ existing: Set[Tuple] = set()
+ with conn.cursor() as cur:
+ for i in range(0, len(pk_values), chunk_size):
+ chunk = pk_values[i:i + chunk_size]
+ execute_values(cur, sql, chunk, page_size=len(chunk))
+ for row in cur.fetchall():
+ existing.add(tuple(row))
+ return existing
+
+
+def _cast_value(value, data_type: str):
+ """类型转换"""
+ if value is None:
+ return None
+ dt = (data_type or "").lower()
+ if dt in ("integer", "bigint", "smallint"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return int(value)
+ except Exception:
+ return None
+ if dt in ("numeric", "double precision", "real", "decimal"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return float(value)
+ except Exception:
+ return None
+ if dt.startswith("timestamp") or dt in ("date", "time", "interval"):
+ return value if isinstance(value, (str, datetime)) else None
+ return value
+
+
+def _normalize_scalar(value):
+ """规范化标量值"""
+ if value == "" or value == "{}" or value == "[]":
+ return None
+ return value
+
+
+class MissingDataBackfiller:
+ """丢失数据补全器"""
+
+ def __init__(
+ self,
+ cfg: AppConfig,
+ logger: logging.Logger,
+ dry_run: bool = False,
+ ):
+ self.cfg = cfg
+ self.logger = logger
+ self.dry_run = dry_run
+ self.tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ self.store_id = int(cfg.get("app.store_id") or 0)
+
+ # API 客户端
+ self.api = APIClient(
+ base_url=cfg["api"]["base_url"],
+ token=cfg["api"]["token"],
+ timeout=int(cfg["api"].get("timeout_sec") or 20),
+ retry_max=int(cfg["api"].get("retries", {}).get("max_attempts") or 3),
+ headers_extra=cfg["api"].get("headers_extra") or {},
+ )
+
+ # 数据库连接(DatabaseConnection 构造时已设置 autocommit=False)
+ self.db = DatabaseConnection(dsn=cfg["db"]["dsn"], session=cfg["db"].get("session"))
+
+ def close(self):
+ """关闭连接"""
+ if self.db:
+ self.db.close()
+
+ def backfill_from_gap_check(
+ self,
+ *,
+ start: datetime,
+ end: datetime,
+ task_codes: Optional[str] = None,
+ page_size: int = 200,
+ chunk_size: int = 500,
+ ) -> Dict[str, Any]:
+ """
+ 运行 gap check 并补全丢失数据
+
+ Returns:
+ 补全结果统计
+ """
+ self.logger.info("数据补全开始 起始=%s 结束=%s", start.isoformat(), end.isoformat())
+
+ # 计算窗口大小
+ total_seconds = max(0, int((end - start).total_seconds()))
+ if total_seconds >= 86400:
+ window_days = max(1, total_seconds // 86400)
+ window_hours = 0
+ else:
+ window_days = 0
+ window_hours = max(1, total_seconds // 3600 or 1)
+
+ # 运行 gap check
+ self.logger.info("正在执行缺失检查...")
+ gap_result = run_gap_check(
+ cfg=self.cfg,
+ start=start,
+ end=end,
+ window_days=window_days,
+ window_hours=window_hours,
+ page_size=page_size,
+ chunk_size=chunk_size,
+ sample_limit=10000, # 获取所有丢失样本
+ sleep_per_window=0,
+ sleep_per_page=0,
+ task_codes=task_codes or "",
+ from_cutoff=False,
+ cutoff_overlap_hours=24,
+ allow_small_window=True,
+ logger=self.logger,
+ )
+
+ total_missing = gap_result.get("total_missing", 0)
+ if total_missing == 0:
+ self.logger.info("数据完整,无缺失记录")
+ return {"backfilled": 0, "errors": 0, "details": []}
+
+ self.logger.info("缺失检查完成 总缺失=%s", total_missing)
+
+ # 补全每个任务的丢失数据
+ results = []
+ total_backfilled = 0
+ total_errors = 0
+
+ for task_result in gap_result.get("results", []):
+ task_code = task_result.get("task_code")
+ missing = task_result.get("missing", 0)
+ missing_samples = task_result.get("missing_samples", [])
+
+ if missing == 0:
+ continue
+
+ self.logger.info(
+ "开始补全任务 任务=%s 缺失=%s 样本数=%s",
+ task_code, missing, len(missing_samples)
+ )
+
+ try:
+ backfilled = self._backfill_task(
+ task_code=task_code,
+ table=task_result.get("table"),
+ pk_columns=task_result.get("pk_columns", []),
+ missing_samples=missing_samples,
+ start=start,
+ end=end,
+ page_size=page_size,
+ chunk_size=chunk_size,
+ )
+ results.append({
+ "task_code": task_code,
+ "missing": missing,
+ "backfilled": backfilled,
+ "error": None,
+ })
+ total_backfilled += backfilled
+ except Exception as exc:
+ self.logger.exception("补全失败 任务=%s", task_code)
+ results.append({
+ "task_code": task_code,
+ "missing": missing,
+ "backfilled": 0,
+ "error": str(exc),
+ })
+ total_errors += 1
+
+ self.logger.info(
+ "数据补全完成 总缺失=%s 已补全=%s 错误数=%s",
+ total_missing, total_backfilled, total_errors
+ )
+
+ return {
+ "total_missing": total_missing,
+ "backfilled": total_backfilled,
+ "errors": total_errors,
+ "details": results,
+ }
+
+ def _backfill_task(
+ self,
+ *,
+ task_code: str,
+ table: str,
+ pk_columns: List[str],
+ missing_samples: List[Dict],
+ start: datetime,
+ end: datetime,
+ page_size: int,
+ chunk_size: int,
+ ) -> int:
+ """补全单个任务的丢失数据"""
+ spec = _get_spec(task_code)
+ if not spec:
+ self.logger.warning("未找到任务规格 任务=%s", task_code)
+ return 0
+
+ if not pk_columns:
+ pk_columns = _get_table_pk_columns(self.db.conn, table)
+
+ if not pk_columns:
+ self.logger.warning("未找到主键列 任务=%s 表=%s", task_code, table)
+ return 0
+
+ # 提取丢失的 PK 值
+ missing_pks: Set[Tuple] = set()
+ for sample in missing_samples:
+ pk_tuple = tuple(sample.get(col) for col in pk_columns)
+ if all(v is not None for v in pk_tuple):
+ missing_pks.add(pk_tuple)
+
+ if not missing_pks:
+ self.logger.info("无缺失主键 任务=%s", task_code)
+ return 0
+
+ self.logger.info(
+ "开始获取数据 任务=%s 缺失主键数=%s",
+ task_code, len(missing_pks)
+ )
+
+ # 从 API 获取数据并过滤出丢失的记录
+ params = self._build_params(spec, start, end)
+
+ backfilled = 0
+ cols_info = _get_table_columns(self.db.conn, table)
+ db_json_cols_lower = {
+ c[0].lower() for c in cols_info
+ if c[1] in ("json", "jsonb") or c[2] in ("json", "jsonb")
+ }
+ col_names = [c[0] for c in cols_info]
+
+ try:
+ for page_no, records, _, response_payload in self.api.iter_paginated(
+ endpoint=spec.endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=spec.data_path,
+ list_key=spec.list_key,
+ ):
+ # 过滤出丢失的记录
+ records_to_insert = []
+ for rec in records:
+ if not isinstance(rec, dict):
+ continue
+ pk_tuple = _pk_tuple_from_record(rec, pk_columns)
+ if pk_tuple and pk_tuple in missing_pks:
+ records_to_insert.append(rec)
+
+ if not records_to_insert:
+ continue
+
+ # 插入丢失的记录
+ if self.dry_run:
+ backfilled += len(records_to_insert)
+ self.logger.info(
+ "模拟运行 任务=%s 页=%s 将插入=%s",
+ task_code, page_no, len(records_to_insert)
+ )
+ else:
+ inserted = self._insert_records(
+ table=table,
+ records=records_to_insert,
+ cols_info=cols_info,
+ pk_columns=pk_columns,
+ db_json_cols_lower=db_json_cols_lower,
+ )
+ backfilled += inserted
+ self.logger.info(
+ "已插入 任务=%s 页=%s 数量=%s",
+ task_code, page_no, inserted
+ )
+
+ if not self.dry_run:
+ self.db.conn.commit()
+
+ self.logger.info("任务补全完成 任务=%s 已补全=%s", task_code, backfilled)
+ return backfilled
+
+ except Exception:
+ self.db.conn.rollback()
+ raise
+
+ def _build_params(
+ self,
+ spec: OdsTaskSpec,
+ start: datetime,
+ end: datetime,
+ ) -> Dict:
+ """构建 API 请求参数"""
+ base: Dict[str, Any] = {}
+ if spec.include_site_id:
+ if spec.endpoint == "/TenantGoods/GetGoodsInventoryList":
+ base["siteId"] = [self.store_id]
+ else:
+ base["siteId"] = self.store_id
+
+ if spec.requires_window and spec.time_fields:
+ start_key, end_key = spec.time_fields
+ base[start_key] = TypeParser.format_timestamp(start, self.tz)
+ base[end_key] = TypeParser.format_timestamp(end, self.tz)
+
+ # 合并公共参数
+ common = self.cfg.get("api.params", {}) or {}
+ if isinstance(common, dict):
+ merged = {**common, **base}
+ else:
+ merged = base
+
+ merged.update(spec.extra_params or {})
+ return merged
+
+ def _insert_records(
+ self,
+ *,
+ table: str,
+ records: List[Dict],
+ cols_info: List[Tuple[str, str, str]],
+ pk_columns: List[str],
+ db_json_cols_lower: Set[str],
+ ) -> int:
+ """插入记录到数据库"""
+ if not records:
+ return 0
+
+ col_names = [c[0] for c in cols_info]
+ quoted_cols = ", ".join(f'"{c}"' for c in col_names)
+ sql = f"INSERT INTO {table} ({quoted_cols}) VALUES %s"
+ if pk_columns:
+ pk_clause = ", ".join(f'"{c}"' for c in pk_columns)
+ sql += f" ON CONFLICT ({pk_clause}) DO NOTHING"
+
+ now = datetime.now(self.tz)
+ json_dump = lambda v: json.dumps(v, ensure_ascii=False)
+
+ params: List[Tuple] = []
+ for rec in records:
+ merged_rec = _merge_record_layers(rec)
+
+ # 检查 PK
+ if pk_columns:
+ missing_pk = False
+ for pk in pk_columns:
+ pk_val = _get_value_case_insensitive(merged_rec, pk)
+ if pk_val is None or pk_val == "":
+ missing_pk = True
+ break
+ if missing_pk:
+ continue
+
+ row_vals: List[Any] = []
+ for (col_name, data_type, _udt) in cols_info:
+ col_lower = col_name.lower()
+ if col_lower == "payload":
+ row_vals.append(Json(rec, dumps=json_dump))
+ continue
+ if col_lower == "source_file":
+ row_vals.append("backfill")
+ continue
+ if col_lower == "source_endpoint":
+ row_vals.append("backfill")
+ continue
+ if col_lower == "fetched_at":
+ row_vals.append(now)
+ continue
+
+ value = _normalize_scalar(_get_value_case_insensitive(merged_rec, col_name))
+ if col_lower in db_json_cols_lower:
+ row_vals.append(Json(value, dumps=json_dump) if value is not None else None)
+ continue
+
+ row_vals.append(_cast_value(value, data_type))
+
+ params.append(tuple(row_vals))
+
+ if not params:
+ return 0
+
+ inserted = 0
+ with self.db.conn.cursor() as cur:
+ for i in range(0, len(params), 200):
+ chunk = params[i:i + 200]
+ execute_values(cur, sql, chunk, page_size=len(chunk))
+ if cur.rowcount is not None and cur.rowcount > 0:
+ inserted += int(cur.rowcount)
+
+ return inserted
+
+
+def run_backfill(
+ *,
+ cfg: AppConfig,
+ start: datetime,
+ end: datetime,
+ task_codes: Optional[str] = None,
+ dry_run: bool = False,
+ page_size: int = 200,
+ chunk_size: int = 500,
+ logger: logging.Logger,
+) -> Dict[str, Any]:
+ """
+ 运行数据补全
+
+ Args:
+ cfg: 应用配置
+ start: 开始时间
+ end: 结束时间
+ task_codes: 指定任务代码(逗号分隔)
+ dry_run: 是否仅预览
+ page_size: API 分页大小
+ chunk_size: 数据库批量大小
+ logger: 日志记录器
+
+ Returns:
+ 补全结果
+ """
+ backfiller = MissingDataBackfiller(cfg, logger, dry_run)
+ try:
+ return backfiller.backfill_from_gap_check(
+ start=start,
+ end=end,
+ task_codes=task_codes,
+ page_size=page_size,
+ chunk_size=chunk_size,
+ )
+ finally:
+ backfiller.close()
+
+
+def main() -> int:
+ _reconfigure_stdout_utf8()
+
+ ap = argparse.ArgumentParser(description="补全丢失的 ODS 数据")
+ ap.add_argument("--start", default="2025-07-01", help="开始日期 (默认: 2025-07-01)")
+ ap.add_argument("--end", default="", help="结束日期 (默认: 当前时间)")
+ ap.add_argument("--task-codes", default="", help="指定任务代码(逗号分隔,留空=全部)")
+ ap.add_argument("--dry-run", action="store_true", help="仅预览,不实际写入")
+ ap.add_argument("--page-size", type=int, default=200, help="API 分页大小 (默认: 200)")
+ ap.add_argument("--chunk-size", type=int, default=500, help="数据库批量大小 (默认: 500)")
+ ap.add_argument("--log-file", default="", help="日志文件路径")
+ ap.add_argument("--log-dir", default="", help="日志目录")
+ ap.add_argument("--log-level", default="INFO", help="日志级别 (默认: INFO)")
+ ap.add_argument("--no-log-console", action="store_true", help="禁用控制台日志")
+ args = ap.parse_args()
+
+ log_dir = Path(args.log_dir) if args.log_dir else (PROJECT_ROOT / "logs")
+ log_file = Path(args.log_file) if args.log_file else build_log_path(log_dir, "backfill_missing")
+ log_console = not args.no_log_console
+
+ with configure_logging(
+ "backfill_missing",
+ log_file,
+ level=args.log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg = AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+
+ start = _parse_dt(args.start, tz)
+ end = _parse_dt(args.end, tz, is_end=True) if args.end else datetime.now(tz)
+
+ result = run_backfill(
+ cfg=cfg,
+ start=start,
+ end=end,
+ task_codes=args.task_codes or None,
+ dry_run=args.dry_run,
+ page_size=args.page_size,
+ chunk_size=args.chunk_size,
+ logger=logger,
+ )
+
+ logger.info("=" * 60)
+ logger.info("补全完成!")
+ logger.info(" 总丢失: %s", result.get("total_missing", 0))
+ logger.info(" 已补全: %s", result.get("backfilled", 0))
+ logger.info(" 错误数: %s", result.get("errors", 0))
+ logger.info("=" * 60)
+
+ # 输出详细结果
+ for detail in result.get("details", []):
+ if detail.get("error"):
+ logger.error(
+ " %s: 丢失=%s 补全=%s 错误=%s",
+ detail.get("task_code"),
+ detail.get("missing"),
+ detail.get("backfilled"),
+ detail.get("error"),
+ )
+ elif detail.get("backfilled", 0) > 0:
+ logger.info(
+ " %s: 丢失=%s 补全=%s",
+ detail.get("task_code"),
+ detail.get("missing"),
+ detail.get("backfilled"),
+ )
+
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/build_dwd_from_ods.py b/etl_billiards/scripts/build_dwd_from_ods.py
index fe80569..c93716f 100644
--- a/etl_billiards/scripts/build_dwd_from_ods.py
+++ b/etl_billiards/scripts/build_dwd_from_ods.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""Populate PRD DWD tables from ODS payload snapshots."""
from __future__ import annotations
@@ -16,9 +16,9 @@ SQL_STEPS: list[tuple[str, str]] = [
INSERT INTO billiards_dwd.dim_tenant (tenant_id, tenant_name, status)
SELECT DISTINCT tenant_id, 'default' AS tenant_name, 'active' AS status
FROM (
- SELECT tenant_id FROM billiards_ods.ods_order_settle
+ SELECT tenant_id FROM billiards_ods.settlement_records
UNION SELECT tenant_id FROM billiards_ods.ods_order_receipt_detail
- UNION SELECT tenant_id FROM billiards_ods.ods_member_profile
+ UNION SELECT tenant_id FROM billiards_ods.member_profiles
) s
WHERE tenant_id IS NOT NULL
ON CONFLICT (tenant_id) DO UPDATE SET updated_at = now();
@@ -30,7 +30,7 @@ SQL_STEPS: list[tuple[str, str]] = [
INSERT INTO billiards_dwd.dim_site (site_id, tenant_id, site_name, status)
SELECT DISTINCT site_id, MAX(tenant_id) AS tenant_id, 'default' AS site_name, 'active' AS status
FROM (
- SELECT site_id, tenant_id FROM billiards_ods.ods_order_settle
+ SELECT site_id, tenant_id FROM billiards_ods.settlement_records
UNION SELECT site_id, tenant_id FROM billiards_ods.ods_order_receipt_detail
UNION SELECT site_id, tenant_id FROM billiards_ods.ods_table_info
) s
@@ -84,7 +84,7 @@ SQL_STEPS: list[tuple[str, str]] = [
"""
INSERT INTO billiards_dwd.dim_member_card_type (card_type_id, card_type_name, discount_rate)
SELECT DISTINCT card_type_id, card_type_name, discount_rate
- FROM billiards_ods.ods_member_card
+ FROM billiards_ods.member_stored_value_cards
WHERE card_type_id IS NOT NULL
ON CONFLICT (card_type_id) DO UPDATE SET
card_type_name = EXCLUDED.card_type_name,
@@ -119,10 +119,10 @@ SQL_STEPS: list[tuple[str, str]] = [
prof.wechat_id,
prof.alipay_id,
prof.remarks
- FROM billiards_ods.ods_member_profile prof
+ FROM billiards_ods.member_profiles prof
LEFT JOIN (
SELECT DISTINCT site_id, member_id, card_type_id AS member_type_id, card_type_name AS member_type_name
- FROM billiards_ods.ods_member_card
+ FROM billiards_ods.member_stored_value_cards
) card
ON prof.site_id = card.site_id AND prof.member_id = card.member_id
WHERE prof.member_id IS NOT NULL
@@ -167,7 +167,7 @@ SQL_STEPS: list[tuple[str, str]] = [
"""
INSERT INTO billiards_dwd.dim_assistant (assistant_id, assistant_name, mobile, status)
SELECT DISTINCT assistant_id, assistant_name, mobile, status
- FROM billiards_ods.ods_assistant_account
+ FROM billiards_ods.assistant_accounts_master
WHERE assistant_id IS NOT NULL
ON CONFLICT (assistant_id) DO UPDATE SET
assistant_name = EXCLUDED.assistant_name,
@@ -181,7 +181,7 @@ SQL_STEPS: list[tuple[str, str]] = [
"""
INSERT INTO billiards_dwd.dim_pay_method (pay_method_code, pay_method_name, is_stored_value, status)
SELECT DISTINCT pay_method_code, pay_method_name, FALSE AS is_stored_value, 'active' AS status
- FROM billiards_ods.ods_payment_record
+ FROM billiards_ods.payment_transactions
WHERE pay_method_code IS NOT NULL
ON CONFLICT (pay_method_code) DO UPDATE SET
pay_method_name = EXCLUDED.pay_method_name,
@@ -250,7 +250,7 @@ SQL_STEPS: list[tuple[str, str]] = [
final_table_fee,
FALSE AS is_canceled,
NULL::TIMESTAMPTZ AS cancel_time
- FROM billiards_ods.ods_table_use_log
+ FROM billiards_ods.table_fee_transactions_log
ON CONFLICT (site_id, ledger_id) DO NOTHING;
""",
),
@@ -325,7 +325,7 @@ SQL_STEPS: list[tuple[str, str]] = [
pay_time,
relate_type,
relate_id
- FROM billiards_ods.ods_payment_record
+ FROM billiards_ods.payment_transactions
ON CONFLICT (site_id, pay_id) DO NOTHING;
""",
),
@@ -346,7 +346,7 @@ SQL_STEPS: list[tuple[str, str]] = [
refund_amount,
refund_time,
status
- FROM billiards_ods.ods_refund_record
+ FROM billiards_ods.refund_transactions
ON CONFLICT (site_id, refund_id) DO NOTHING;
""",
),
@@ -369,7 +369,7 @@ SQL_STEPS: list[tuple[str, str]] = [
balance_before,
balance_after,
change_time
- FROM billiards_ods.ods_balance_change
+ FROM billiards_ods.member_balance_changes
ON CONFLICT (site_id, change_id) DO NOTHING;
""",
),
@@ -423,3 +423,4 @@ def main() -> int:
if __name__ == "__main__":
raise SystemExit(main())
+
diff --git a/etl_billiards/scripts/build_dws_order_summary.py b/etl_billiards/scripts/build_dws_order_summary.py
index ea62ec6..ad964cc 100644
--- a/etl_billiards/scripts/build_dws_order_summary.py
+++ b/etl_billiards/scripts/build_dws_order_summary.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-"""Recompute billiards_dws.dws_order_summary from DWD fact tables."""
+"""Recompute billiards_dws.dws_order_summary from DWD tables (dwd_*)."""
from __future__ import annotations
import argparse
@@ -15,119 +15,90 @@ from database.connection import DatabaseConnection # noqa: E402
SQL_BUILD_SUMMARY = r"""
-WITH table_fee AS (
+WITH base AS (
+ SELECT
+ sh.site_id,
+ sh.order_settle_id,
+ sh.order_trade_no,
+ COALESCE(sh.pay_time, sh.create_time)::date AS order_date,
+ sh.tenant_id,
+ sh.member_id,
+ COALESCE(sh.is_bind_member, FALSE) AS member_flag,
+ (COALESCE(sh.consume_money, 0) = 0 AND COALESCE(sh.pay_amount, 0) > 0) AS recharge_order_flag,
+ COALESCE(sh.member_discount_amount, 0) AS member_discount_amount,
+ COALESCE(sh.adjust_amount, 0) AS manual_discount_amount,
+ COALESCE(sh.pay_amount, 0) AS total_paid_amount,
+ COALESCE(sh.balance_amount, 0) + COALESCE(sh.recharge_card_amount, 0) + COALESCE(sh.gift_card_amount, 0) AS stored_card_deduct,
+ COALESCE(sh.coupon_amount, 0) AS total_coupon_deduction,
+ COALESCE(sh.table_charge_money, 0) AS settle_table_fee_amount,
+ COALESCE(sh.assistant_pd_money, 0) + COALESCE(sh.assistant_cx_money, 0) AS settle_assistant_service_amount,
+ COALESCE(sh.real_goods_money, 0) AS settle_goods_amount
+ FROM billiards_dwd.dwd_settlement_head sh
+ WHERE (%(site_id)s IS NULL OR sh.site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR COALESCE(sh.pay_time, sh.create_time)::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR COALESCE(sh.pay_time, sh.create_time)::date <= %(end_date)s)
+),
+table_fee AS (
SELECT
site_id,
order_settle_id,
- order_trade_no,
- MIN(member_id) AS member_id,
- SUM(COALESCE(final_table_fee, 0)) AS table_fee_amount,
- SUM(COALESCE(member_discount_amount, 0)) AS member_discount_amount,
- SUM(COALESCE(manual_discount_amount, 0)) AS manual_discount_amount,
- SUM(COALESCE(original_table_fee, 0)) AS original_table_fee,
- MIN(start_time) AS first_time
- FROM billiards_dwd.fact_table_usage
- WHERE (%(site_id)s IS NULL OR site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR start_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR start_time::date <= %(end_date)s)
- AND COALESCE(is_canceled, FALSE) = FALSE
- GROUP BY site_id, order_settle_id, order_trade_no
+ SUM(COALESCE(real_table_charge_money, 0)) AS table_fee_amount
+ FROM billiards_dwd.dwd_table_fee_log
+ WHERE COALESCE(is_delete, 0) = 0
+ AND (%(site_id)s IS NULL OR site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR start_use_time::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR start_use_time::date <= %(end_date)s)
+ GROUP BY site_id, order_settle_id
),
assistant_fee AS (
SELECT
site_id,
order_settle_id,
- order_trade_no,
- MIN(member_id) AS member_id,
- SUM(COALESCE(final_fee, 0)) AS assistant_service_amount,
- SUM(COALESCE(member_discount_amount, 0)) AS member_discount_amount,
- SUM(COALESCE(manual_discount_amount, 0)) AS manual_discount_amount,
- SUM(COALESCE(original_fee, 0)) AS original_fee,
- MIN(start_time) AS first_time
- FROM billiards_dwd.fact_assistant_service
- WHERE (%(site_id)s IS NULL OR site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR start_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR start_time::date <= %(end_date)s)
- AND COALESCE(is_canceled, FALSE) = FALSE
- GROUP BY site_id, order_settle_id, order_trade_no
+ SUM(COALESCE(ledger_amount, 0)) AS assistant_service_amount
+ FROM billiards_dwd.dwd_assistant_service_log
+ WHERE COALESCE(is_delete, 0) = 0
+ AND (%(site_id)s IS NULL OR site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR start_use_time::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR start_use_time::date <= %(end_date)s)
+ GROUP BY site_id, order_settle_id
),
goods_fee AS (
SELECT
site_id,
order_settle_id,
- order_trade_no,
- MIN(member_id) AS member_id,
- SUM(COALESCE(final_amount, 0)) FILTER (WHERE COALESCE(is_gift, FALSE) = FALSE) AS goods_amount,
- SUM(COALESCE(discount_amount, 0)) FILTER (WHERE COALESCE(is_gift, FALSE) = FALSE) AS goods_discount_amount,
- SUM(COALESCE(original_amount, 0)) FILTER (WHERE COALESCE(is_gift, FALSE) = FALSE) AS goods_original_amount,
- COUNT(*) FILTER (WHERE COALESCE(is_gift, FALSE) = FALSE) AS item_count,
- SUM(COALESCE(quantity, 0)) FILTER (WHERE COALESCE(is_gift, FALSE) = FALSE) AS total_item_quantity,
- MIN(sale_time) AS first_time
- FROM billiards_dwd.fact_sale_item
- WHERE (%(site_id)s IS NULL OR site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR sale_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR sale_time::date <= %(end_date)s)
- GROUP BY site_id, order_settle_id, order_trade_no
+ COUNT(*) AS item_count,
+ SUM(COALESCE(ledger_count, 0)) AS total_item_quantity,
+ SUM(COALESCE(real_goods_money, 0)) AS goods_amount
+ FROM billiards_dwd.dwd_store_goods_sale
+ WHERE COALESCE(is_delete, 0) = 0
+ AND (%(site_id)s IS NULL OR site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR create_time::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR create_time::date <= %(end_date)s)
+ GROUP BY site_id, order_settle_id
),
-coupon_usage AS (
+group_fee AS (
SELECT
site_id,
order_settle_id,
- order_trade_no,
- MIN(member_id) AS member_id,
- SUM(COALESCE(deduct_amount, 0)) AS coupon_deduction,
- SUM(COALESCE(settle_price, 0)) AS settle_price,
- MIN(used_time) AS first_time
- FROM billiards_dwd.fact_coupon_usage
- WHERE (%(site_id)s IS NULL OR site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR used_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR used_time::date <= %(end_date)s)
- GROUP BY site_id, order_settle_id, order_trade_no
-),
-payments AS (
- SELECT
- fp.site_id,
- fp.order_settle_id,
- fp.order_trade_no,
- MIN(fp.member_id) AS member_id,
- SUM(COALESCE(fp.pay_amount, 0)) AS total_paid_amount,
- SUM(COALESCE(fp.pay_amount, 0)) FILTER (WHERE COALESCE(pm.is_stored_value, FALSE)) AS stored_card_deduct,
- SUM(COALESCE(fp.pay_amount, 0)) FILTER (WHERE NOT COALESCE(pm.is_stored_value, FALSE)) AS external_paid_amount,
- MIN(fp.pay_time) AS first_time
- FROM billiards_dwd.fact_payment fp
- LEFT JOIN billiards_dwd.dim_pay_method pm ON fp.pay_method_code = pm.pay_method_code
- WHERE (%(site_id)s IS NULL OR fp.site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR fp.pay_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR fp.pay_time::date <= %(end_date)s)
- GROUP BY fp.site_id, fp.order_settle_id, fp.order_trade_no
+ SUM(COALESCE(ledger_amount, 0)) AS group_amount
+ FROM billiards_dwd.dwd_groupbuy_redemption
+ WHERE COALESCE(is_delete, 0) = 0
+ AND (%(site_id)s IS NULL OR site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR create_time::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR create_time::date <= %(end_date)s)
+ GROUP BY site_id, order_settle_id
),
refunds AS (
SELECT
- site_id,
- order_settle_id,
- order_trade_no,
- SUM(COALESCE(refund_amount, 0)) AS refund_amount
- FROM billiards_dwd.fact_refund
- WHERE (%(site_id)s IS NULL OR site_id = %(site_id)s)
- AND (%(start_date)s IS NULL OR refund_time::date >= %(start_date)s)
- AND (%(end_date)s IS NULL OR refund_time::date <= %(end_date)s)
- GROUP BY site_id, order_settle_id, order_trade_no
-),
-combined_ids AS (
- SELECT site_id, order_settle_id, order_trade_no FROM table_fee
- UNION
- SELECT site_id, order_settle_id, order_trade_no FROM assistant_fee
- UNION
- SELECT site_id, order_settle_id, order_trade_no FROM goods_fee
- UNION
- SELECT site_id, order_settle_id, order_trade_no FROM coupon_usage
- UNION
- SELECT site_id, order_settle_id, order_trade_no FROM payments
- UNION
- SELECT site_id, order_settle_id, order_trade_no FROM refunds
-),
-site_dim AS (
- SELECT site_id, tenant_id FROM billiards_dwd.dim_site
+ r.site_id,
+ r.relate_id AS order_settle_id,
+ SUM(COALESCE(rx.refund_amount, 0)) AS refund_amount
+ FROM billiards_dwd.dwd_refund r
+ LEFT JOIN billiards_dwd.dwd_refund_ex rx ON r.refund_id = rx.refund_id
+ WHERE (%(site_id)s IS NULL OR r.site_id = %(site_id)s)
+ AND (%(start_date)s IS NULL OR r.pay_time::date >= %(start_date)s)
+ AND (%(end_date)s IS NULL OR r.pay_time::date <= %(end_date)s)
+ GROUP BY r.site_id, r.relate_id
)
INSERT INTO billiards_dws.dws_order_summary (
site_id,
@@ -166,58 +137,50 @@ INSERT INTO billiards_dws.dws_order_summary (
updated_at
)
SELECT
- c.site_id,
- c.order_settle_id,
- c.order_trade_no,
- COALESCE(tf.first_time, af.first_time, gf.first_time, pay.first_time, cu.first_time)::date AS order_date,
- sd.tenant_id,
- COALESCE(tf.member_id, af.member_id, gf.member_id, cu.member_id, pay.member_id) AS member_id,
- COALESCE(tf.member_id, af.member_id, gf.member_id, cu.member_id, pay.member_id) IS NOT NULL AS member_flag,
- -- recharge flag: no consumption side but has payments
- (COALESCE(tf.table_fee_amount, 0) + COALESCE(af.assistant_service_amount, 0) + COALESCE(gf.goods_amount, 0) + COALESCE(cu.settle_price, 0) = 0)
- AND COALESCE(pay.total_paid_amount, 0) > 0 AS recharge_order_flag,
+ b.site_id,
+ b.order_settle_id,
+ b.order_trade_no::text AS order_trade_no,
+ b.order_date,
+ b.tenant_id,
+ b.member_id,
+ b.member_flag,
+ b.recharge_order_flag,
COALESCE(gf.item_count, 0) AS item_count,
COALESCE(gf.total_item_quantity, 0) AS total_item_quantity,
- COALESCE(tf.table_fee_amount, 0) AS table_fee_amount,
- COALESCE(af.assistant_service_amount, 0) AS assistant_service_amount,
- COALESCE(gf.goods_amount, 0) AS goods_amount,
- COALESCE(cu.settle_price, 0) AS group_amount,
- COALESCE(cu.coupon_deduction, 0) AS total_coupon_deduction,
- COALESCE(tf.member_discount_amount, 0) + COALESCE(af.member_discount_amount, 0) + COALESCE(gf.goods_discount_amount, 0) AS member_discount_amount,
- COALESCE(tf.manual_discount_amount, 0) + COALESCE(af.manual_discount_amount, 0) AS manual_discount_amount,
- COALESCE(tf.original_table_fee, 0) + COALESCE(af.original_fee, 0) + COALESCE(gf.goods_original_amount, 0) AS order_original_amount,
- COALESCE(tf.table_fee_amount, 0) + COALESCE(af.assistant_service_amount, 0) + COALESCE(gf.goods_amount, 0) + COALESCE(cu.settle_price, 0) - COALESCE(cu.coupon_deduction, 0) AS order_final_amount,
- COALESCE(pay.stored_card_deduct, 0) AS stored_card_deduct,
- COALESCE(pay.external_paid_amount, 0) AS external_paid_amount,
- COALESCE(pay.total_paid_amount, 0) AS total_paid_amount,
- COALESCE(tf.table_fee_amount, 0) AS book_table_flow,
- COALESCE(af.assistant_service_amount, 0) AS book_assistant_flow,
- COALESCE(gf.goods_amount, 0) AS book_goods_flow,
- COALESCE(cu.settle_price, 0) AS book_group_flow,
- COALESCE(tf.table_fee_amount, 0) + COALESCE(af.assistant_service_amount, 0) + COALESCE(gf.goods_amount, 0) + COALESCE(cu.settle_price, 0) AS book_order_flow,
- CASE
- WHEN (COALESCE(tf.table_fee_amount, 0) + COALESCE(af.assistant_service_amount, 0) + COALESCE(gf.goods_amount, 0) + COALESCE(cu.settle_price, 0) = 0)
- THEN 0
- ELSE COALESCE(pay.external_paid_amount, 0)
- END AS order_effective_consume_cash,
- CASE
- WHEN (COALESCE(tf.table_fee_amount, 0) + COALESCE(af.assistant_service_amount, 0) + COALESCE(gf.goods_amount, 0) + COALESCE(cu.settle_price, 0) = 0)
- THEN COALESCE(pay.external_paid_amount, 0)
- ELSE 0
- END AS order_effective_recharge_cash,
- COALESCE(pay.external_paid_amount, 0) + COALESCE(cu.settle_price, 0) AS order_effective_flow,
+ COALESCE(tf.table_fee_amount, b.settle_table_fee_amount) AS table_fee_amount,
+ COALESCE(af.assistant_service_amount, b.settle_assistant_service_amount) AS assistant_service_amount,
+ COALESCE(gf.goods_amount, b.settle_goods_amount) AS goods_amount,
+ COALESCE(gr.group_amount, 0) AS group_amount,
+ b.total_coupon_deduction AS total_coupon_deduction,
+ b.member_discount_amount AS member_discount_amount,
+ b.manual_discount_amount AS manual_discount_amount,
+ -- approximate original amount: final + discounts/coupon
+ (b.total_paid_amount + b.total_coupon_deduction + b.member_discount_amount + b.manual_discount_amount) AS order_original_amount,
+ b.total_paid_amount AS order_final_amount,
+ b.stored_card_deduct AS stored_card_deduct,
+ GREATEST(b.total_paid_amount - b.stored_card_deduct, 0) AS external_paid_amount,
+ b.total_paid_amount AS total_paid_amount,
+ COALESCE(tf.table_fee_amount, b.settle_table_fee_amount) AS book_table_flow,
+ COALESCE(af.assistant_service_amount, b.settle_assistant_service_amount) AS book_assistant_flow,
+ COALESCE(gf.goods_amount, b.settle_goods_amount) AS book_goods_flow,
+ COALESCE(gr.group_amount, 0) AS book_group_flow,
+ COALESCE(tf.table_fee_amount, b.settle_table_fee_amount)
+ + COALESCE(af.assistant_service_amount, b.settle_assistant_service_amount)
+ + COALESCE(gf.goods_amount, b.settle_goods_amount)
+ + COALESCE(gr.group_amount, 0) AS book_order_flow,
+ GREATEST(b.total_paid_amount - b.stored_card_deduct, 0) AS order_effective_consume_cash,
+ 0 AS order_effective_recharge_cash,
+ b.total_paid_amount AS order_effective_flow,
COALESCE(rf.refund_amount, 0) AS refund_amount,
- (COALESCE(pay.external_paid_amount, 0) + COALESCE(cu.settle_price, 0)) - COALESCE(rf.refund_amount, 0) AS net_income,
+ b.total_paid_amount - COALESCE(rf.refund_amount, 0) AS net_income,
now() AS created_at,
now() AS updated_at
-FROM combined_ids c
-LEFT JOIN table_fee tf ON c.site_id = tf.site_id AND c.order_settle_id = tf.order_settle_id
-LEFT JOIN assistant_fee af ON c.site_id = af.site_id AND c.order_settle_id = af.order_settle_id
-LEFT JOIN goods_fee gf ON c.site_id = gf.site_id AND c.order_settle_id = gf.order_settle_id
-LEFT JOIN coupon_usage cu ON c.site_id = cu.site_id AND c.order_settle_id = cu.order_settle_id
-LEFT JOIN payments pay ON c.site_id = pay.site_id AND c.order_settle_id = pay.order_settle_id
-LEFT JOIN refunds rf ON c.site_id = rf.site_id AND c.order_settle_id = rf.order_settle_id
-LEFT JOIN site_dim sd ON c.site_id = sd.site_id
+FROM base b
+LEFT JOIN table_fee tf ON b.site_id = tf.site_id AND b.order_settle_id = tf.order_settle_id
+LEFT JOIN assistant_fee af ON b.site_id = af.site_id AND b.order_settle_id = af.order_settle_id
+LEFT JOIN goods_fee gf ON b.site_id = gf.site_id AND b.order_settle_id = gf.order_settle_id
+LEFT JOIN group_fee gr ON b.site_id = gr.site_id AND b.order_settle_id = gr.order_settle_id
+LEFT JOIN refunds rf ON b.site_id = rf.site_id AND b.order_settle_id = rf.order_settle_id
ON CONFLICT (site_id, order_settle_id) DO UPDATE SET
order_trade_no = EXCLUDED.order_trade_no,
order_date = EXCLUDED.order_date,
diff --git a/etl_billiards/scripts/check_data_integrity.py b/etl_billiards/scripts/check_data_integrity.py
new file mode 100644
index 0000000..ffe34f7
--- /dev/null
+++ b/etl_billiards/scripts/check_data_integrity.py
@@ -0,0 +1,169 @@
+# -*- coding: utf-8 -*-
+"""Run data integrity checks across API -> ODS -> DWD."""
+from __future__ import annotations
+
+import argparse
+import json
+import sys
+from datetime import datetime
+from pathlib import Path
+from zoneinfo import ZoneInfo
+
+from dateutil import parser as dtparser
+
+from config.settings import AppConfig
+from quality.integrity_checker import (
+ IntegrityWindow,
+ compute_last_etl_end,
+ run_integrity_history,
+ run_integrity_window,
+)
+from utils.logging_utils import build_log_path, configure_logging
+from utils.windowing import split_window
+
+
+def _parse_dt(value: str, tz: ZoneInfo) -> datetime:
+ dt = dtparser.parse(value)
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=tz)
+ return dt.astimezone(tz)
+
+
+def main() -> int:
+ if hasattr(sys.stdout, "reconfigure"):
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+
+ ap = argparse.ArgumentParser(description="Data integrity checks (API -> ODS -> DWD)")
+ ap.add_argument("--mode", choices=["history", "window"], default="history")
+ ap.add_argument("--start", default="2025-07-01", help="history start date (default: 2025-07-01)")
+ ap.add_argument("--end", default="", help="history end datetime (default: last ETL end)")
+ ap.add_argument("--window-start", default="", help="window start datetime (mode=window)")
+ ap.add_argument("--window-end", default="", help="window end datetime (mode=window)")
+ ap.add_argument("--window-split-unit", default="", help="split unit (month/none), default from config")
+ ap.add_argument("--window-compensation-hours", type=int, default=None, help="window compensation hours, default from config")
+ ap.add_argument("--include-dimensions", action="store_true", help="include dimension tables in ODS->DWD checks")
+ ap.add_argument("--ods-task-codes", default="", help="comma-separated ODS task codes for API checks")
+ ap.add_argument("--out", default="", help="output JSON path")
+ ap.add_argument("--log-file", default="", help="log file path")
+ ap.add_argument("--log-dir", default="", help="log directory")
+ ap.add_argument("--log-level", default="INFO", help="log level")
+ ap.add_argument("--no-log-console", action="store_true", help="disable console logging")
+ args = ap.parse_args()
+
+ log_dir = Path(args.log_dir) if args.log_dir else (Path(__file__).resolve().parent / "logs")
+ log_file = Path(args.log_file) if args.log_file else build_log_path(log_dir, "data_integrity")
+ log_console = not args.no_log_console
+
+ with configure_logging(
+ "data_integrity",
+ log_file,
+ level=args.log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg = AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ report_path = Path(args.out) if args.out else None
+
+ if args.mode == "window":
+ if not args.window_start or not args.window_end:
+ raise SystemExit("window-start and window-end are required for mode=window")
+ start_dt = _parse_dt(args.window_start, tz)
+ end_dt = _parse_dt(args.window_end, tz)
+ split_unit = (args.window_split_unit or cfg.get("run.window_split.unit", "month") or "month").strip()
+ comp_hours = args.window_compensation_hours
+ if comp_hours is None:
+ comp_hours = cfg.get("run.window_split.compensation_hours", 0)
+
+ windows = split_window(
+ start_dt,
+ end_dt,
+ tz=tz,
+ split_unit=split_unit,
+ compensation_hours=comp_hours,
+ )
+ if not windows:
+ windows = [(start_dt, end_dt)]
+
+ window_reports = []
+ total_missing = 0
+ total_errors = 0
+ for idx, (seg_start, seg_end) in enumerate(windows, start=1):
+ window = IntegrityWindow(
+ start=seg_start,
+ end=seg_end,
+ label=f"segment_{idx}",
+ granularity="window",
+ )
+ payload = run_integrity_window(
+ cfg=cfg,
+ window=window,
+ include_dimensions=args.include_dimensions,
+ task_codes=args.ods_task_codes,
+ logger=logger,
+ write_report=False,
+ report_path=None,
+ window_split_unit="none",
+ window_compensation_hours=0,
+ )
+ window_reports.append(payload)
+ total_missing += int(payload.get("api_to_ods", {}).get("total_missing") or 0)
+ total_errors += int(payload.get("api_to_ods", {}).get("total_errors") or 0)
+
+ overall_start = windows[0][0]
+ overall_end = windows[-1][1]
+ report = {
+ "mode": "window",
+ "window": {
+ "start": overall_start.isoformat(),
+ "end": overall_end.isoformat(),
+ "segments": len(windows),
+ },
+ "windows": window_reports,
+ "api_to_ods": {
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ },
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ "generated_at": datetime.now(tz).isoformat(),
+ }
+ if report_path is None:
+ root = Path(__file__).resolve().parents[1]
+ stamp = datetime.now(tz).strftime("%Y%m%d_%H%M%S")
+ report_path = root / "reports" / f"data_integrity_window_{stamp}.json"
+ report_path.parent.mkdir(parents=True, exist_ok=True)
+ report_path.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
+ report["report_path"] = str(report_path)
+ logger.info("REPORT_WRITTEN path=%s", report.get("report_path"))
+ else:
+ start_dt = _parse_dt(args.start, tz)
+ if args.end:
+ end_dt = _parse_dt(args.end, tz)
+ else:
+ end_dt = compute_last_etl_end(cfg) or datetime.now(tz)
+ report = run_integrity_history(
+ cfg=cfg,
+ start_dt=start_dt,
+ end_dt=end_dt,
+ include_dimensions=args.include_dimensions,
+ task_codes=args.ods_task_codes,
+ logger=logger,
+ write_report=True,
+ report_path=report_path,
+ )
+ logger.info("REPORT_WRITTEN path=%s", report.get("report_path"))
+ logger.info(
+ "SUMMARY missing=%s errors=%s",
+ report.get("total_missing"),
+ report.get("total_errors"),
+ )
+
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/check_ods_gaps.py b/etl_billiards/scripts/check_ods_gaps.py
new file mode 100644
index 0000000..58df520
--- /dev/null
+++ b/etl_billiards/scripts/check_ods_gaps.py
@@ -0,0 +1,874 @@
+# -*- coding: utf-8 -*-
+"""
+Check missing ODS records by comparing API primary keys vs ODS table primary keys.
+
+Default range:
+ start = 2025-07-01 00:00:00
+ end = now
+
+For update runs, use --from-cutoff to derive the start time from ODS max(fetched_at),
+then backtrack by --cutoff-overlap-hours.
+"""
+from __future__ import annotations
+
+import argparse
+import json
+import logging
+import time as time_mod
+import sys
+from datetime import datetime, time, timedelta
+from pathlib import Path
+from typing import Iterable, Sequence
+from zoneinfo import ZoneInfo
+
+from dateutil import parser as dtparser
+from psycopg2.extras import execute_values
+
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from api.client import APIClient
+from config.settings import AppConfig
+from database.connection import DatabaseConnection
+from models.parsers import TypeParser
+from tasks.ods_tasks import ENABLED_ODS_CODES, ODS_TASK_SPECS
+from utils.logging_utils import build_log_path, configure_logging
+from utils.windowing import split_window
+
+DEFAULT_START = "2025-07-01"
+MIN_COMPLETENESS_WINDOW_DAYS = 30
+
+
+def _reconfigure_stdout_utf8() -> None:
+ if hasattr(sys.stdout, "reconfigure"):
+ try:
+ sys.stdout.reconfigure(encoding="utf-8")
+ except Exception:
+ pass
+
+
+def _parse_dt(value: str, tz: ZoneInfo, *, is_end: bool) -> datetime:
+ raw = (value or "").strip()
+ if not raw:
+ raise ValueError("empty datetime")
+ has_time = any(ch in raw for ch in (":", "T"))
+ dt = dtparser.parse(raw)
+ if dt.tzinfo is None:
+ dt = dt.replace(tzinfo=tz)
+ else:
+ dt = dt.astimezone(tz)
+ if not has_time:
+ dt = dt.replace(hour=23 if is_end else 0, minute=59 if is_end else 0, second=59 if is_end else 0, microsecond=0)
+ return dt
+
+
+def _iter_windows(start: datetime, end: datetime, window_size: timedelta) -> Iterable[tuple[datetime, datetime]]:
+ if window_size.total_seconds() <= 0:
+ raise ValueError("window_size must be > 0")
+ cur = start
+ while cur < end:
+ nxt = min(cur + window_size, end)
+ yield cur, nxt
+ cur = nxt
+
+
+def _merge_record_layers(record: dict) -> dict:
+ merged = record
+ data_part = merged.get("data")
+ while isinstance(data_part, dict):
+ merged = {**data_part, **merged}
+ data_part = data_part.get("data")
+ settle_inner = merged.get("settleList")
+ if isinstance(settle_inner, dict):
+ merged = {**settle_inner, **merged}
+ return merged
+
+
+def _get_value_case_insensitive(record: dict | None, col: str | None):
+ if record is None or col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+
+def _normalize_pk_value(value):
+ if value is None:
+ return None
+ if isinstance(value, str) and value.isdigit():
+ try:
+ return int(value)
+ except Exception:
+ return value
+ return value
+
+
+def _chunked(seq: Sequence, size: int) -> Iterable[Sequence]:
+ if size <= 0:
+ size = 500
+ for i in range(0, len(seq), size):
+ yield seq[i : i + size]
+
+
+def _get_table_pk_columns(conn, table: str) -> list[str]:
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT kcu.column_name
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.constraint_name = kcu.constraint_name
+ AND tc.table_schema = kcu.table_schema
+ WHERE tc.constraint_type = 'PRIMARY KEY'
+ AND tc.table_schema = %s
+ AND tc.table_name = %s
+ ORDER BY kcu.ordinal_position
+ """
+ with conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ return [r[0] for r in cur.fetchall()]
+
+
+def _fetch_existing_pk_set(conn, table: str, pk_cols: Sequence[str], pk_values: list[tuple], chunk_size: int) -> set[tuple]:
+ if not pk_values:
+ return set()
+ select_cols = ", ".join(f't."{c}"' for c in pk_cols)
+ value_cols = ", ".join(f'"{c}"' for c in pk_cols)
+ join_cond = " AND ".join(f't."{c}" = v."{c}"' for c in pk_cols)
+ sql = (
+ f"SELECT {select_cols} FROM {table} t "
+ f"JOIN (VALUES %s) AS v({value_cols}) ON {join_cond}"
+ )
+ existing: set[tuple] = set()
+ with conn.cursor() as cur:
+ for chunk in _chunked(pk_values, chunk_size):
+ execute_values(cur, sql, chunk, page_size=len(chunk))
+ for row in cur.fetchall():
+ existing.add(tuple(row))
+ return existing
+
+
+def _merge_common_params(cfg: AppConfig, task_code: str, base: dict) -> dict:
+ merged: dict = {}
+ common = cfg.get("api.params", {}) or {}
+ if isinstance(common, dict):
+ merged.update(common)
+ scoped = cfg.get(f"api.params.{task_code.lower()}", {}) or {}
+ if isinstance(scoped, dict):
+ merged.update(scoped)
+ merged.update(base)
+ return merged
+
+
+def _build_params(cfg: AppConfig, spec, store_id: int, window_start: datetime | None, window_end: datetime | None) -> dict:
+ base: dict = {}
+ if spec.include_site_id:
+ if spec.endpoint == "/TenantGoods/GetGoodsInventoryList":
+ base["siteId"] = [store_id]
+ else:
+ base["siteId"] = store_id
+ if spec.requires_window and spec.time_fields and window_start and window_end:
+ start_key, end_key = spec.time_fields
+ base[start_key] = TypeParser.format_timestamp(window_start, ZoneInfo(cfg.get("app.timezone", "Asia/Taipei")))
+ base[end_key] = TypeParser.format_timestamp(window_end, ZoneInfo(cfg.get("app.timezone", "Asia/Taipei")))
+ base.update(spec.extra_params or {})
+ return _merge_common_params(cfg, spec.code, base)
+
+
+def _pk_tuple_from_record(record: dict, pk_cols: Sequence[str]) -> tuple | None:
+ merged = _merge_record_layers(record)
+ values = []
+ for col in pk_cols:
+ val = _normalize_pk_value(_get_value_case_insensitive(merged, col))
+ if val is None or val == "":
+ return None
+ values.append(val)
+ return tuple(values)
+
+
+def _pk_tuple_from_ticket_candidate(value) -> tuple | None:
+ val = _normalize_pk_value(value)
+ if val is None or val == "":
+ return None
+ return (val,)
+
+
+def _format_missing_sample(pk_cols: Sequence[str], pk_tuple: tuple) -> dict:
+ return {col: pk_tuple[idx] for idx, col in enumerate(pk_cols)}
+
+
+def _check_spec(
+ *,
+ client: APIClient,
+ db_conn,
+ cfg: AppConfig,
+ tz: ZoneInfo,
+ logger: logging.Logger,
+ spec,
+ store_id: int,
+ start: datetime | None,
+ end: datetime | None,
+ windows: list[tuple[datetime, datetime]] | None,
+ page_size: int,
+ chunk_size: int,
+ sample_limit: int,
+ sleep_per_window: float,
+ sleep_per_page: float,
+) -> dict:
+ result = {
+ "task_code": spec.code,
+ "table": spec.table_name,
+ "endpoint": spec.endpoint,
+ "pk_columns": [],
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": None,
+ }
+
+ pk_cols = _get_table_pk_columns(db_conn, spec.table_name)
+ result["pk_columns"] = pk_cols
+ if not pk_cols:
+ result["errors"] = 1
+ result["error_detail"] = "no primary key columns found"
+ return result
+
+ if spec.requires_window and spec.time_fields:
+ if not start or not end:
+ result["errors"] = 1
+ result["error_detail"] = "missing start/end for windowed endpoint"
+ return result
+ windows = list(windows or [(start, end)])
+ else:
+ windows = [(None, None)]
+
+ logger.info(
+ "CHECK_START task=%s table=%s windows=%s start=%s end=%s",
+ spec.code,
+ spec.table_name,
+ len(windows),
+ start.isoformat() if start else None,
+ end.isoformat() if end else None,
+ )
+ missing_seen: set[tuple] = set()
+
+ for window_idx, (window_start, window_end) in enumerate(windows, start=1):
+ window_label = (
+ f"{window_start.isoformat()}~{window_end.isoformat()}"
+ if window_start and window_end
+ else "FULL"
+ )
+ logger.info(
+ "WINDOW_START task=%s idx=%s window=%s",
+ spec.code,
+ window_idx,
+ window_label,
+ )
+ window_pages = 0
+ window_records = 0
+ window_missing = 0
+ window_skipped = 0
+ params = _build_params(cfg, spec, store_id, window_start, window_end)
+ try:
+ for page_no, records, _, _ in client.iter_paginated(
+ endpoint=spec.endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=spec.data_path,
+ list_key=spec.list_key,
+ ):
+ window_pages += 1
+ window_records += len(records)
+ result["pages"] += 1
+ result["records"] += len(records)
+ pk_tuples: list[tuple] = []
+ for rec in records:
+ if not isinstance(rec, dict):
+ result["skipped_missing_pk"] += 1
+ window_skipped += 1
+ continue
+ pk_tuple = _pk_tuple_from_record(rec, pk_cols)
+ if not pk_tuple:
+ result["skipped_missing_pk"] += 1
+ window_skipped += 1
+ continue
+ pk_tuples.append(pk_tuple)
+
+ if not pk_tuples:
+ continue
+
+ result["records_with_pk"] += len(pk_tuples)
+ pk_unique = list(dict.fromkeys(pk_tuples))
+ existing = _fetch_existing_pk_set(db_conn, spec.table_name, pk_cols, pk_unique, chunk_size)
+ for pk_tuple in pk_unique:
+ if pk_tuple in existing:
+ continue
+ if pk_tuple in missing_seen:
+ continue
+ missing_seen.add(pk_tuple)
+ result["missing"] += 1
+ window_missing += 1
+ if len(result["missing_samples"]) < sample_limit:
+ result["missing_samples"].append(_format_missing_sample(pk_cols, pk_tuple))
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.debug(
+ "PAGE task=%s idx=%s page=%s records=%s missing=%s skipped=%s",
+ spec.code,
+ window_idx,
+ page_no,
+ len(records),
+ window_missing,
+ window_skipped,
+ )
+ if sleep_per_page > 0:
+ time_mod.sleep(sleep_per_page)
+ except Exception as exc:
+ result["errors"] += 1
+ result["error_detail"] = f"{type(exc).__name__}: {exc}"
+ logger.exception(
+ "WINDOW_ERROR task=%s idx=%s window=%s error=%s",
+ spec.code,
+ window_idx,
+ window_label,
+ result["error_detail"],
+ )
+ break
+ logger.info(
+ "WINDOW_DONE task=%s idx=%s window=%s pages=%s records=%s missing=%s skipped=%s",
+ spec.code,
+ window_idx,
+ window_label,
+ window_pages,
+ window_records,
+ window_missing,
+ window_skipped,
+ )
+ if sleep_per_window > 0:
+ logger.debug(
+ "SLEEP_WINDOW task=%s idx=%s seconds=%.2f",
+ spec.code,
+ window_idx,
+ sleep_per_window,
+ )
+ time_mod.sleep(sleep_per_window)
+
+ return result
+
+
+def _check_settlement_tickets(
+ *,
+ client: APIClient,
+ db_conn,
+ cfg: AppConfig,
+ tz: ZoneInfo,
+ logger: logging.Logger,
+ store_id: int,
+ start: datetime | None,
+ end: datetime | None,
+ windows: list[tuple[datetime, datetime]] | None,
+ page_size: int,
+ chunk_size: int,
+ sample_limit: int,
+ sleep_per_window: float,
+ sleep_per_page: float,
+) -> dict:
+ table_name = "billiards_ods.settlement_ticket_details"
+ pk_cols = _get_table_pk_columns(db_conn, table_name)
+ result = {
+ "task_code": "ODS_SETTLEMENT_TICKET",
+ "table": table_name,
+ "endpoint": "/Order/GetOrderSettleTicketNew",
+ "pk_columns": pk_cols,
+ "records": 0,
+ "records_with_pk": 0,
+ "missing": 0,
+ "missing_samples": [],
+ "pages": 0,
+ "skipped_missing_pk": 0,
+ "errors": 0,
+ "error_detail": None,
+ "source_endpoint": "/PayLog/GetPayLogListPage",
+ }
+
+ if not pk_cols:
+ result["errors"] = 1
+ result["error_detail"] = "no primary key columns found"
+ return result
+ if not start or not end:
+ result["errors"] = 1
+ result["error_detail"] = "missing start/end for ticket check"
+ return result
+
+ missing_seen: set[tuple] = set()
+ pay_endpoint = "/PayLog/GetPayLogListPage"
+
+ windows = list(windows or [(start, end)])
+ logger.info(
+ "CHECK_START task=%s table=%s windows=%s start=%s end=%s",
+ result["task_code"],
+ table_name,
+ len(windows),
+ start.isoformat() if start else None,
+ end.isoformat() if end else None,
+ )
+
+ for window_idx, (window_start, window_end) in enumerate(windows, start=1):
+ window_label = f"{window_start.isoformat()}~{window_end.isoformat()}"
+ logger.info(
+ "WINDOW_START task=%s idx=%s window=%s",
+ result["task_code"],
+ window_idx,
+ window_label,
+ )
+ window_pages = 0
+ window_records = 0
+ window_missing = 0
+ window_skipped = 0
+ base = {
+ "siteId": store_id,
+ "StartPayTime": TypeParser.format_timestamp(window_start, tz),
+ "EndPayTime": TypeParser.format_timestamp(window_end, tz),
+ }
+ params = _merge_common_params(cfg, "ODS_PAYMENT", base)
+ try:
+ for page_no, records, _, _ in client.iter_paginated(
+ endpoint=pay_endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=("data",),
+ list_key=None,
+ ):
+ window_pages += 1
+ window_records += len(records)
+ result["pages"] += 1
+ result["records"] += len(records)
+ pk_tuples: list[tuple] = []
+ for rec in records:
+ if not isinstance(rec, dict):
+ result["skipped_missing_pk"] += 1
+ window_skipped += 1
+ continue
+ relate_id = TypeParser.parse_int(
+ (rec or {}).get("relateId")
+ or (rec or {}).get("orderSettleId")
+ or (rec or {}).get("order_settle_id")
+ )
+ pk_tuple = _pk_tuple_from_ticket_candidate(relate_id)
+ if not pk_tuple:
+ result["skipped_missing_pk"] += 1
+ window_skipped += 1
+ continue
+ pk_tuples.append(pk_tuple)
+
+ if not pk_tuples:
+ continue
+
+ result["records_with_pk"] += len(pk_tuples)
+ pk_unique = list(dict.fromkeys(pk_tuples))
+ existing = _fetch_existing_pk_set(db_conn, table_name, pk_cols, pk_unique, chunk_size)
+ for pk_tuple in pk_unique:
+ if pk_tuple in existing:
+ continue
+ if pk_tuple in missing_seen:
+ continue
+ missing_seen.add(pk_tuple)
+ result["missing"] += 1
+ window_missing += 1
+ if len(result["missing_samples"]) < sample_limit:
+ result["missing_samples"].append(_format_missing_sample(pk_cols, pk_tuple))
+ if logger.isEnabledFor(logging.DEBUG):
+ logger.debug(
+ "PAGE task=%s idx=%s page=%s records=%s missing=%s skipped=%s",
+ result["task_code"],
+ window_idx,
+ page_no,
+ len(records),
+ window_missing,
+ window_skipped,
+ )
+ if sleep_per_page > 0:
+ time_mod.sleep(sleep_per_page)
+ except Exception as exc:
+ result["errors"] += 1
+ result["error_detail"] = f"{type(exc).__name__}: {exc}"
+ logger.exception(
+ "WINDOW_ERROR task=%s idx=%s window=%s error=%s",
+ result["task_code"],
+ window_idx,
+ window_label,
+ result["error_detail"],
+ )
+ break
+ logger.info(
+ "WINDOW_DONE task=%s idx=%s window=%s pages=%s records=%s missing=%s skipped=%s",
+ result["task_code"],
+ window_idx,
+ window_label,
+ window_pages,
+ window_records,
+ window_missing,
+ window_skipped,
+ )
+ if sleep_per_window > 0:
+ logger.debug(
+ "SLEEP_WINDOW task=%s idx=%s seconds=%.2f",
+ result["task_code"],
+ window_idx,
+ sleep_per_window,
+ )
+ time_mod.sleep(sleep_per_window)
+
+ return result
+
+
+def _compute_ods_cutoff(conn, ods_tables: Sequence[str]) -> datetime | None:
+ values: list[datetime] = []
+ with conn.cursor() as cur:
+ for table in ods_tables:
+ try:
+ cur.execute(f"SELECT MAX(fetched_at) FROM {table}")
+ row = cur.fetchone()
+ if row and row[0]:
+ values.append(row[0])
+ except Exception:
+ continue
+ if not values:
+ return None
+ return min(values)
+
+
+def _resolve_window_from_cutoff(
+ *,
+ conn,
+ ods_tables: Sequence[str],
+ tz: ZoneInfo,
+ overlap_hours: int,
+) -> tuple[datetime, datetime, datetime | None]:
+ cutoff = _compute_ods_cutoff(conn, ods_tables)
+ now = datetime.now(tz)
+ if cutoff is None:
+ start = now - timedelta(hours=max(1, overlap_hours))
+ return start, now, None
+ if cutoff.tzinfo is None:
+ cutoff = cutoff.replace(tzinfo=tz)
+ else:
+ cutoff = cutoff.astimezone(tz)
+ start = cutoff - timedelta(hours=max(0, overlap_hours))
+ return start, now, cutoff
+
+
+def run_gap_check(
+ *,
+ cfg: AppConfig | None,
+ start: datetime | str | None,
+ end: datetime | str | None,
+ window_days: int,
+ window_hours: int,
+ page_size: int,
+ chunk_size: int,
+ sample_limit: int,
+ sleep_per_window: float,
+ sleep_per_page: float,
+ task_codes: str,
+ from_cutoff: bool,
+ cutoff_overlap_hours: int,
+ allow_small_window: bool,
+ logger: logging.Logger,
+ window_split_unit: str | None = None,
+ window_compensation_hours: int | None = None,
+) -> dict:
+ cfg = cfg or AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ store_id = int(cfg.get("app.store_id") or 0)
+
+ if not cfg.get("api.token"):
+ raise ValueError("missing api.token; please set API_TOKEN in .env")
+
+ window_days = int(window_days)
+ window_hours = int(window_hours)
+ split_unit = (window_split_unit or cfg.get("run.window_split.unit", "month") or "month").strip()
+ comp_hours = window_compensation_hours
+ if comp_hours is None:
+ comp_hours = cfg.get("run.window_split.compensation_hours", 0)
+
+ use_split = split_unit.lower() not in ("", "none", "off", "false", "0")
+ if not use_split and not from_cutoff and not allow_small_window:
+ min_hours = MIN_COMPLETENESS_WINDOW_DAYS * 24
+ if window_hours > 0:
+ if window_hours < min_hours:
+ logger.warning(
+ "window_hours=%s too small for completeness check; adjust to %s",
+ window_hours,
+ min_hours,
+ )
+ window_hours = min_hours
+ elif window_days < MIN_COMPLETENESS_WINDOW_DAYS:
+ logger.warning(
+ "window_days=%s too small for completeness check; adjust to %s",
+ window_days,
+ MIN_COMPLETENESS_WINDOW_DAYS,
+ )
+ window_days = MIN_COMPLETENESS_WINDOW_DAYS
+
+ cutoff = None
+ if from_cutoff:
+ db_tmp = DatabaseConnection(dsn=cfg["db"]["dsn"], session=cfg["db"].get("session"))
+ ods_tables = [s.table_name for s in ODS_TASK_SPECS if s.code in ENABLED_ODS_CODES]
+ start, end, cutoff = _resolve_window_from_cutoff(
+ conn=db_tmp.conn,
+ ods_tables=ods_tables,
+ tz=tz,
+ overlap_hours=cutoff_overlap_hours,
+ )
+ db_tmp.close()
+ else:
+ if not start:
+ start = DEFAULT_START
+ if not end:
+ end = datetime.now(tz)
+ if isinstance(start, str):
+ start = _parse_dt(start, tz, is_end=False)
+ if isinstance(end, str):
+ end = _parse_dt(end, tz, is_end=True)
+
+
+ windows = None
+ if use_split:
+ windows = split_window(
+ start,
+ end,
+ tz=tz,
+ split_unit=split_unit,
+ compensation_hours=comp_hours,
+ )
+ else:
+ adjusted = split_window(
+ start,
+ end,
+ tz=tz,
+ split_unit="none",
+ compensation_hours=comp_hours,
+ )
+ if adjusted:
+ start, end = adjusted[0]
+ window_size = timedelta(hours=window_hours) if window_hours > 0 else timedelta(days=window_days)
+ windows = list(_iter_windows(start, end, window_size))
+
+ if windows:
+ start, end = windows[0][0], windows[-1][1]
+
+ logger.info(
+ "START range=%s~%s window_days=%s window_hours=%s split_unit=%s comp_hours=%s page_size=%s chunk_size=%s",
+ start.isoformat() if isinstance(start, datetime) else None,
+ end.isoformat() if isinstance(end, datetime) else None,
+ window_days,
+ window_hours,
+ split_unit,
+ comp_hours,
+ page_size,
+ chunk_size,
+ )
+ if cutoff:
+ logger.info("CUTOFF=%s overlap_hours=%s", cutoff.isoformat(), cutoff_overlap_hours)
+
+ client = APIClient(
+ base_url=cfg["api"]["base_url"],
+ token=cfg["api"]["token"],
+ timeout=int(cfg["api"].get("timeout_sec") or 20),
+ retry_max=int(cfg["api"].get("retries", {}).get("max_attempts") or 3),
+ headers_extra=cfg["api"].get("headers_extra") or {},
+ )
+
+ db_conn = DatabaseConnection(dsn=cfg["db"]["dsn"], session=cfg["db"].get("session"))
+ try:
+ db_conn.conn.rollback()
+ except Exception:
+ pass
+ db_conn.conn.autocommit = True
+ try:
+ task_filter = {t.strip().upper() for t in (task_codes or "").split(",") if t.strip()}
+ specs = [s for s in ODS_TASK_SPECS if s.code in ENABLED_ODS_CODES]
+ if task_filter:
+ specs = [s for s in specs if s.code in task_filter]
+
+ results: list[dict] = []
+ for spec in specs:
+ if spec.code == "ODS_SETTLEMENT_TICKET":
+ continue
+ result = _check_spec(
+ client=client,
+ db_conn=db_conn.conn,
+ cfg=cfg,
+ tz=tz,
+ logger=logger,
+ spec=spec,
+ store_id=store_id,
+ start=start,
+ end=end,
+ windows=windows,
+ page_size=page_size,
+ chunk_size=chunk_size,
+ sample_limit=sample_limit,
+ sleep_per_window=sleep_per_window,
+ sleep_per_page=sleep_per_page,
+ )
+ results.append(result)
+ logger.info(
+ "CHECK_DONE task=%s missing=%s records=%s errors=%s",
+ result.get("task_code"),
+ result.get("missing"),
+ result.get("records"),
+ result.get("errors"),
+ )
+
+ if (not task_filter) or ("ODS_SETTLEMENT_TICKET" in task_filter):
+ ticket_result = _check_settlement_tickets(
+ client=client,
+ db_conn=db_conn.conn,
+ cfg=cfg,
+ tz=tz,
+ logger=logger,
+ store_id=store_id,
+ start=start,
+ end=end,
+ windows=windows,
+ page_size=page_size,
+ chunk_size=chunk_size,
+ sample_limit=sample_limit,
+ sleep_per_window=sleep_per_window,
+ sleep_per_page=sleep_per_page,
+ )
+ results.append(ticket_result)
+ logger.info(
+ "CHECK_DONE task=%s missing=%s records=%s errors=%s",
+ ticket_result.get("task_code"),
+ ticket_result.get("missing"),
+ ticket_result.get("records"),
+ ticket_result.get("errors"),
+ )
+
+ total_missing = sum(int(r.get("missing") or 0) for r in results)
+ total_errors = sum(int(r.get("errors") or 0) for r in results)
+
+ payload = {
+ "window_split_unit": split_unit,
+ "window_compensation_hours": comp_hours,
+ "start": start.isoformat() if isinstance(start, datetime) else None,
+ "end": end.isoformat() if isinstance(end, datetime) else None,
+ "cutoff": cutoff.isoformat() if cutoff else None,
+ "window_days": window_days,
+ "window_hours": window_hours,
+ "page_size": page_size,
+ "chunk_size": chunk_size,
+ "sample_limit": sample_limit,
+ "store_id": store_id,
+ "base_url": cfg.get("api.base_url"),
+ "results": results,
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ "generated_at": datetime.now(tz).isoformat(),
+ }
+ return payload
+ finally:
+ db_conn.close()
+
+
+def main() -> int:
+ _reconfigure_stdout_utf8()
+ ap = argparse.ArgumentParser(description="Check missing ODS records by comparing API vs ODS PKs.")
+ ap.add_argument("--start", default=DEFAULT_START, help="start datetime (default: 2025-07-01)")
+ ap.add_argument("--end", default="", help="end datetime (default: now)")
+ ap.add_argument("--window-days", type=int, default=1, help="days per API window (default: 1)")
+ ap.add_argument("--window-hours", type=int, default=0, help="hours per API window (default: 0)")
+ ap.add_argument("--window-split-unit", default="", help="split unit (month/none), default from config")
+ ap.add_argument("--window-compensation-hours", type=int, default=None, help="window compensation hours, default from config")
+ ap.add_argument("--page-size", type=int, default=200, help="API page size (default: 200)")
+ ap.add_argument("--chunk-size", type=int, default=500, help="DB query chunk size (default: 500)")
+ ap.add_argument("--sample-limit", type=int, default=50, help="max missing PK samples per table")
+ ap.add_argument("--sleep-per-window-seconds", type=float, default=0, help="sleep seconds after each window")
+ ap.add_argument("--sleep-per-page-seconds", type=float, default=0, help="sleep seconds after each page")
+ ap.add_argument("--task-codes", default="", help="comma-separated task codes to check (optional)")
+ ap.add_argument("--out", default="", help="output JSON path (optional)")
+ ap.add_argument("--tag", default="", help="tag suffix for output filename")
+ ap.add_argument("--from-cutoff", action="store_true", help="derive start from ODS cutoff")
+ ap.add_argument(
+ "--cutoff-overlap-hours",
+ type=int,
+ default=24,
+ help="overlap hours when using --from-cutoff (default: 24)",
+ )
+ ap.add_argument(
+ "--allow-small-window",
+ action="store_true",
+ help="allow windows smaller than default completeness guard",
+ )
+ ap.add_argument("--log-file", default="", help="log file path (default: logs/check_ods_gaps_YYYYMMDD_HHMMSS.log)")
+ ap.add_argument("--log-dir", default="", help="log directory (default: logs)")
+ ap.add_argument("--log-level", default="INFO", help="log level (default: INFO)")
+ ap.add_argument("--no-log-console", action="store_true", help="disable console logging")
+ args = ap.parse_args()
+
+ log_dir = Path(args.log_dir) if args.log_dir else (PROJECT_ROOT / "logs")
+ log_file = Path(args.log_file) if args.log_file else build_log_path(log_dir, "check_ods_gaps", args.tag)
+ log_console = not args.no_log_console
+
+ with configure_logging(
+ "ods_gap_check",
+ log_file,
+ level=args.log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg = AppConfig.load({})
+ payload = run_gap_check(
+ cfg=cfg,
+ start=args.start,
+ end=args.end,
+ window_days=args.window_days,
+ window_hours=args.window_hours,
+ page_size=args.page_size,
+ chunk_size=args.chunk_size,
+ sample_limit=args.sample_limit,
+ sleep_per_window=args.sleep_per_window_seconds,
+ sleep_per_page=args.sleep_per_page_seconds,
+ task_codes=args.task_codes,
+ from_cutoff=args.from_cutoff,
+ cutoff_overlap_hours=args.cutoff_overlap_hours,
+ allow_small_window=args.allow_small_window,
+ logger=logger,
+ window_split_unit=args.window_split_unit or None,
+ window_compensation_hours=args.window_compensation_hours,
+ )
+
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+ if args.out:
+ out_path = Path(args.out)
+ else:
+ tag = f"_{args.tag}" if args.tag else ""
+ stamp = datetime.now(tz).strftime("%Y%m%d_%H%M%S")
+ out_path = PROJECT_ROOT / "reports" / f"ods_gap_check{tag}_{stamp}.json"
+ out_path.parent.mkdir(parents=True, exist_ok=True)
+ out_path.write_text(json.dumps(payload, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
+ logger.info("REPORT_WRITTEN path=%s", out_path)
+ logger.info(
+ "SUMMARY missing=%s errors=%s",
+ payload.get("total_missing"),
+ payload.get("total_errors"),
+ )
+
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/check_ods_json_vs_table.py b/etl_billiards/scripts/check_ods_json_vs_table.py
new file mode 100644
index 0000000..df188d6
--- /dev/null
+++ b/etl_billiards/scripts/check_ods_json_vs_table.py
@@ -0,0 +1,117 @@
+# -*- coding: utf-8 -*-
+"""
+ODS JSON 字段核对脚本:对照当前数据库中的 ODS 表字段,检查示例 JSON(默认目录 export/test-json-doc)
+是否包含同名键,并输出每表未命中的字段,便于补充映射或确认确实无源字段。
+
+使用方法:
+ set PG_DSN=postgresql://... # 如 .env 中配置
+ python -m etl_billiards.scripts.check_ods_json_vs_table
+"""
+from __future__ import annotations
+
+import json
+import os
+import pathlib
+from typing import Dict, Iterable, Set, Tuple
+
+import psycopg2
+
+from etl_billiards.tasks.manual_ingest_task import ManualIngestTask
+
+
+def _flatten_keys(obj, prefix: str = "") -> Set[str]:
+ """递归展开 JSON 所有键路径,返回形如 data.assistantInfos.id 的集合。列表不保留索引,仅继续向下展开。"""
+ keys: Set[str] = set()
+ if isinstance(obj, dict):
+ for k, v in obj.items():
+ new_prefix = f"{prefix}.{k}" if prefix else k
+ keys.add(new_prefix)
+ keys |= _flatten_keys(v, new_prefix)
+ elif isinstance(obj, list):
+ for item in obj:
+ keys |= _flatten_keys(item, prefix)
+ return keys
+
+
+def _load_json_keys(path: pathlib.Path) -> Tuple[Set[str], dict[str, Set[str]]]:
+ """读取单个 JSON 文件并返回展开后的键集合以及末段->路径列表映射,若文件不存在或无法解析则返回空集合。"""
+ if not path.exists():
+ return set(), {}
+ data = json.loads(path.read_text(encoding="utf-8"))
+ paths = _flatten_keys(data)
+ last_map: dict[str, Set[str]] = {}
+ for p in paths:
+ last = p.split(".")[-1].lower()
+ last_map.setdefault(last, set()).add(p)
+ return paths, last_map
+
+
+def _load_ods_columns(dsn: str) -> Dict[str, Set[str]]:
+ """从数据库读取 billiards_ods.* 的列名集合,按表返回。"""
+ conn = psycopg2.connect(dsn)
+ cur = conn.cursor()
+ cur.execute(
+ """
+ SELECT table_name, column_name
+ FROM information_schema.columns
+ WHERE table_schema='billiards_ods'
+ ORDER BY table_name, ordinal_position
+ """
+ )
+ result: Dict[str, Set[str]] = {}
+ for table, col in cur.fetchall():
+ result.setdefault(table, set()).add(col.lower())
+ cur.close()
+ conn.close()
+ return result
+
+
+def main() -> None:
+ """主流程:遍历 FILE_MAPPING 中的 ODS 表,检查 JSON 键覆盖情况并打印报告。"""
+ dsn = os.environ.get("PG_DSN")
+ json_dir = pathlib.Path(os.environ.get("JSON_DOC_DIR", "export/test-json-doc"))
+
+ ods_cols_map = _load_ods_columns(dsn)
+
+ print(f"使用 JSON 目录: {json_dir}")
+ print(f"连接 DSN: {dsn}")
+ print("=" * 80)
+
+ for keywords, ods_table in ManualIngestTask.FILE_MAPPING:
+ table = ods_table.split(".")[-1]
+ cols = ods_cols_map.get(table, set())
+ file_name = f"{keywords[0]}.json"
+ file_path = json_dir / file_name
+ keys_full, path_map = _load_json_keys(file_path)
+ key_last_parts = set(path_map.keys())
+
+ missing: Set[str] = set()
+ extra_keys: Set[str] = set()
+ present: Set[str] = set()
+ for col in sorted(cols):
+ if col in key_last_parts:
+ present.add(col)
+ else:
+ missing.add(col)
+ for k in key_last_parts:
+ if k not in cols:
+ extra_keys.add(k)
+
+ print(f"[{table}] 文件={file_name} 列数={len(cols)} JSON键(末段)覆盖={len(present)}/{len(cols)}")
+ if missing:
+ print(" 未命中列:", ", ".join(sorted(missing)))
+ else:
+ print(" 未命中列: 无")
+ if extra_keys:
+ extras = []
+ for k in sorted(extra_keys):
+ paths = ", ".join(sorted(path_map.get(k, [])))
+ extras.append(f"{k} ({paths})")
+ print(" JSON 仅有(表无此列):", "; ".join(extras))
+ else:
+ print(" JSON 仅有(表无此列): 无")
+ print("-" * 80)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/etl_billiards/scripts/rebuild_db_and_run_ods_to_dwd.py b/etl_billiards/scripts/rebuild_db_and_run_ods_to_dwd.py
new file mode 100644
index 0000000..c0ecde7
--- /dev/null
+++ b/etl_billiards/scripts/rebuild_db_and_run_ods_to_dwd.py
@@ -0,0 +1,404 @@
+# -*- coding: utf-8 -*-
+"""
+一键重建 ETL 相关 Schema,并执行 ODS → DWD。
+
+本脚本面向“离线示例 JSON 回放”的开发/运维场景,使用当前项目内的任务实现:
+1) (可选)DROP 并重建 schema:`etl_admin` / `billiards_ods` / `billiards_dwd`
+2) 执行 `INIT_ODS_SCHEMA`:创建 `etl_admin` 元数据表 + 执行 `schema_ODS_doc.sql`(内部会做轻量清洗)
+3) 执行 `INIT_DWD_SCHEMA`:执行 `schema_dwd_doc.sql`
+4) 执行 `MANUAL_INGEST`:从本地 JSON 目录灌入 ODS
+5) 执行 `DWD_LOAD_FROM_ODS`:从 ODS 装载到 DWD
+
+用法(推荐):
+ python -m etl_billiards.scripts.rebuild_db_and_run_ods_to_dwd ^
+ --dsn "postgresql://user:pwd@host:5432/db" ^
+ --store-id 1 ^
+ --json-dir "export/test-json-doc" ^
+ --drop-schemas
+
+环境变量(可选):
+ PG_DSN、STORE_ID、INGEST_SOURCE_DIR
+
+日志:
+ 默认同时输出到控制台与文件;文件路径为 `io.log_root/rebuild_db_<时间戳>.log`。
+"""
+
+from __future__ import annotations
+
+import argparse
+import logging
+import os
+import time
+from dataclasses import dataclass
+from pathlib import Path
+from typing import Any
+
+import psycopg2
+
+from etl_billiards.config.settings import AppConfig
+from etl_billiards.database.connection import DatabaseConnection
+from etl_billiards.database.operations import DatabaseOperations
+from etl_billiards.tasks.dwd_load_task import DwdLoadTask
+from etl_billiards.tasks.init_dwd_schema_task import InitDwdSchemaTask
+from etl_billiards.tasks.init_schema_task import InitOdsSchemaTask
+from etl_billiards.tasks.manual_ingest_task import ManualIngestTask
+
+
+DEFAULT_JSON_DIR = "export/test-json-doc"
+
+
+@dataclass(frozen=True)
+class RunArgs:
+ """脚本参数对象(用于减少散落的参数传递)。"""
+
+ dsn: str
+ store_id: int
+ json_dir: str
+ drop_schemas: bool
+ terminate_own_sessions: bool
+ demo: bool
+ only_files: list[str]
+ only_dwd_tables: list[str]
+ stop_after: str | None
+
+
+def _attach_file_logger(log_root: str | Path, filename: str, logger: logging.Logger) -> logging.Handler | None:
+ """
+ 给 root logger 附加文件日志处理器(UTF-8)。
+
+ 说明:
+ - 使用 root logger 是为了覆盖项目中不同命名的 logger(包含第三方/子模块)。
+ - 若创建失败仅记录 warning,不中断主流程。
+
+ 返回值:
+ 创建成功返回 handler(调用方负责 removeHandler/close),失败返回 None。
+ """
+ log_dir = Path(log_root)
+ try:
+ log_dir.mkdir(parents=True, exist_ok=True)
+ except Exception as exc: # noqa: BLE001
+ logger.warning("创建日志目录失败:%s(%s)", log_dir, exc)
+ return None
+
+ log_path = log_dir / filename
+ try:
+ handler: logging.Handler = logging.FileHandler(log_path, encoding="utf-8")
+ except Exception as exc: # noqa: BLE001
+ logger.warning("创建文件日志失败:%s(%s)", log_path, exc)
+ return None
+
+ handler.setLevel(logging.INFO)
+ handler.setFormatter(
+ logging.Formatter(
+ fmt="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S",
+ )
+ )
+ logging.getLogger().addHandler(handler)
+ logger.info("文件日志已启用:%s", log_path)
+ return handler
+
+
+def _parse_args() -> RunArgs:
+ """解析命令行/环境变量参数。"""
+ parser = argparse.ArgumentParser(description="重建 Schema 并执行 ODS→DWD(离线 JSON 回放)")
+ parser.add_argument("--dsn", default=os.environ.get("PG_DSN"), help="PostgreSQL DSN(默认读取 PG_DSN)")
+ parser.add_argument(
+ "--store-id",
+ type=int,
+ default=int(os.environ.get("STORE_ID") or 1),
+ help="门店/租户 store_id(默认读取 STORE_ID,否则为 1)",
+ )
+ parser.add_argument(
+ "--json-dir",
+ default=os.environ.get("INGEST_SOURCE_DIR") or DEFAULT_JSON_DIR,
+ help=f"示例 JSON 目录(默认 {DEFAULT_JSON_DIR},也可读 INGEST_SOURCE_DIR)",
+ )
+ parser.add_argument(
+ "--drop-schemas",
+ action=argparse.BooleanOptionalAction,
+ default=True,
+ help="是否先 DROP 并重建 etl_admin/billiards_ods/billiards_dwd(默认:是)",
+ )
+ parser.add_argument(
+ "--terminate-own-sessions",
+ action=argparse.BooleanOptionalAction,
+ default=True,
+ help="执行 DROP 前是否终止当前用户的 idle-in-transaction 会话(默认:是)",
+ )
+ parser.add_argument(
+ "--demo",
+ action=argparse.BooleanOptionalAction,
+ default=False,
+ help="运行最小 Demo(仅导入 member_profiles 并生成 dim_member/dim_member_ex)",
+ )
+ parser.add_argument(
+ "--only-files",
+ default="",
+ help="仅处理指定 JSON 文件(逗号分隔,不含 .json,例如:member_profiles,settlement_records)",
+ )
+ parser.add_argument(
+ "--only-dwd-tables",
+ default="",
+ help="仅处理指定 DWD 表(逗号分隔,支持完整名或表名,例如:billiards_dwd.dim_member,dim_member_ex)",
+ )
+ parser.add_argument(
+ "--stop-after",
+ default="",
+ help="在指定阶段后停止(可选:DROP_SCHEMAS/INIT_ODS_SCHEMA/INIT_DWD_SCHEMA/MANUAL_INGEST/DWD_LOAD_FROM_ODS/BASIC_VALIDATE)",
+ )
+ args = parser.parse_args()
+
+ if not args.dsn:
+ raise SystemExit("缺少 DSN:请传入 --dsn 或设置环境变量 PG_DSN")
+ only_files = [x.strip().lower() for x in str(args.only_files or "").split(",") if x.strip()]
+ only_dwd_tables = [x.strip().lower() for x in str(args.only_dwd_tables or "").split(",") if x.strip()]
+ stop_after = str(args.stop_after or "").strip().upper() or None
+ return RunArgs(
+ dsn=args.dsn,
+ store_id=args.store_id,
+ json_dir=str(args.json_dir),
+ drop_schemas=bool(args.drop_schemas),
+ terminate_own_sessions=bool(args.terminate_own_sessions),
+ demo=bool(args.demo),
+ only_files=only_files,
+ only_dwd_tables=only_dwd_tables,
+ stop_after=stop_after,
+ )
+
+
+def _build_config(args: RunArgs) -> AppConfig:
+ """构建本次执行所需的最小配置覆盖。"""
+ manual_cfg: dict[str, Any] = {}
+ dwd_cfg: dict[str, Any] = {}
+ if args.demo:
+ manual_cfg["include_files"] = ["member_profiles"]
+ dwd_cfg["only_tables"] = ["billiards_dwd.dim_member", "billiards_dwd.dim_member_ex"]
+ if args.only_files:
+ manual_cfg["include_files"] = args.only_files
+ if args.only_dwd_tables:
+ dwd_cfg["only_tables"] = args.only_dwd_tables
+
+ overrides: dict[str, Any] = {
+ "app": {"store_id": args.store_id},
+ "pipeline": {"flow": "INGEST_ONLY", "ingest_source_dir": args.json_dir},
+ "manual": manual_cfg,
+ "dwd": dwd_cfg,
+ # 离线回放/建仓可能耗时较长,关闭 statement_timeout,避免被默认 30s 中断。
+ # 同时关闭 lock_timeout,避免 DROP/DDL 因锁等待稍久就直接失败。
+ "db": {"dsn": args.dsn, "session": {"statement_timeout_ms": 0, "lock_timeout_ms": 0}},
+ }
+ return AppConfig.load(overrides)
+
+
+def _drop_schemas(db: DatabaseOperations, logger: logging.Logger) -> None:
+ """删除并重建 ETL 相关 schema(具备破坏性,请谨慎)。"""
+ with db.conn.cursor() as cur:
+ # 避免因为其他会话持锁而无限等待;若确实被占用,提示用户先释放/终止阻塞会话。
+ cur.execute("SET lock_timeout TO '5s'")
+ for schema in ("billiards_dwd", "billiards_ods", "etl_admin"):
+ logger.info("DROP SCHEMA IF EXISTS %s CASCADE ...", schema)
+ cur.execute(f'DROP SCHEMA IF EXISTS "{schema}" CASCADE;')
+
+
+def _terminate_own_idle_in_tx(db: DatabaseOperations, logger: logging.Logger) -> int:
+ """终止当前用户在本库中处于 idle-in-transaction 的会话,避免阻塞 DROP/DDL。"""
+ with db.conn.cursor() as cur:
+ cur.execute(
+ """
+ SELECT pid
+ FROM pg_stat_activity
+ WHERE datname = current_database()
+ AND usename = current_user
+ AND pid <> pg_backend_pid()
+ AND state = 'idle in transaction'
+ """
+ )
+ pids = [r[0] for r in cur.fetchall()]
+ killed = 0
+ for pid in pids:
+ cur.execute("SELECT pg_terminate_backend(%s)", (pid,))
+ ok = bool(cur.fetchone()[0])
+ logger.info("终止会话 pid=%s ok=%s", pid, ok)
+ killed += 1 if ok else 0
+ return killed
+
+
+def _run_task(task, logger: logging.Logger) -> dict:
+ """统一运行任务并打印关键结果。"""
+ result = task.execute(None)
+ logger.info("%s: status=%s counts=%s", task.get_task_code(), result.get("status"), result.get("counts"))
+ return result
+
+
+def _basic_validate(db: DatabaseOperations, logger: logging.Logger) -> None:
+ """做最基础的可用性校验:schema 存在、关键表行数可查询。"""
+ checks = [
+ ("billiards_ods", "member_profiles"),
+ ("billiards_ods", "settlement_records"),
+ ("billiards_dwd", "dim_member"),
+ ("billiards_dwd", "dwd_settlement_head"),
+ ]
+ for schema, table in checks:
+ try:
+ rows = db.query(f'SELECT COUNT(1) AS cnt FROM "{schema}"."{table}"')
+ logger.info("校验行数:%s.%s = %s", schema, table, (rows[0] or {}).get("cnt") if rows else None)
+ except Exception as exc: # noqa: BLE001
+ logger.warning("校验失败:%s.%s(%s)", schema, table, exc)
+
+
+def _connect_db_with_retry(cfg: AppConfig, logger: logging.Logger) -> DatabaseConnection:
+ """创建数据库连接(带重试),避免短暂网络抖动导致脚本直接失败。"""
+ dsn = cfg["db"]["dsn"]
+ session = cfg["db"].get("session")
+ connect_timeout = cfg["db"].get("connect_timeout_sec")
+
+ backoffs = [1, 2, 4, 8, 16]
+ last_exc: Exception | None = None
+ for attempt, wait_sec in enumerate([0] + backoffs, start=1):
+ if wait_sec:
+ time.sleep(wait_sec)
+ try:
+ return DatabaseConnection(dsn=dsn, session=session, connect_timeout=connect_timeout)
+ except Exception as exc: # noqa: BLE001
+ last_exc = exc
+ logger.warning("数据库连接失败(第 %s 次):%s", attempt, exc)
+ raise last_exc or RuntimeError("数据库连接失败")
+
+
+def _is_connection_error(exc: Exception) -> bool:
+ """判断是否为连接断开/服务端异常导致的可重试错误。"""
+ return isinstance(exc, (psycopg2.OperationalError, psycopg2.InterfaceError))
+
+
+def _run_stage_with_reconnect(
+ cfg: AppConfig,
+ logger: logging.Logger,
+ stage_name: str,
+ fn,
+ max_attempts: int = 3,
+) -> dict | None:
+ """
+ 运行单个阶段:失败(尤其是连接断开)时自动重连并重试。
+
+ fn: (db_ops) -> dict | None
+ """
+ last_exc: Exception | None = None
+ for attempt in range(1, max_attempts + 1):
+ db_conn = _connect_db_with_retry(cfg, logger)
+ db_ops = DatabaseOperations(db_conn)
+ try:
+ logger.info("阶段开始:%s(第 %s/%s 次)", stage_name, attempt, max_attempts)
+ result = fn(db_ops)
+ logger.info("阶段完成:%s", stage_name)
+ return result
+ except Exception as exc: # noqa: BLE001
+ last_exc = exc
+ logger.exception("阶段失败:%s(第 %s/%s 次):%s", stage_name, attempt, max_attempts, exc)
+ # 连接类错误允许重试;非连接错误直接抛出,避免掩盖逻辑问题。
+ if not _is_connection_error(exc):
+ raise
+ time.sleep(min(2**attempt, 10))
+ finally:
+ try:
+ db_ops.close() # type: ignore[attr-defined]
+ except Exception:
+ pass
+ try:
+ db_conn.close()
+ except Exception:
+ pass
+ raise last_exc or RuntimeError(f"阶段失败:{stage_name}")
+
+
+def main() -> int:
+ """脚本主入口:按顺序重建并跑通 ODS→DWD。"""
+ logging.basicConfig(
+ level=logging.INFO,
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
+ datefmt="%Y-%m-%d %H:%M:%S",
+ )
+ logger = logging.getLogger("etl_billiards.rebuild_db")
+
+ args = _parse_args()
+ cfg = _build_config(args)
+
+ # 默认启用文件日志,便于事后追溯(即便运行失败也应尽早落盘)。
+ file_handler = _attach_file_logger(
+ log_root=cfg["io"]["log_root"],
+ filename=time.strftime("rebuild_db_%Y%m%d-%H%M%S.log"),
+ logger=logger,
+ )
+
+ try:
+ json_dir = Path(args.json_dir)
+ if not json_dir.exists():
+ logger.error("示例 JSON 目录不存在:%s", json_dir)
+ return 2
+
+ def stage_drop(db_ops: DatabaseOperations):
+ if not args.drop_schemas:
+ return None
+ if args.terminate_own_sessions:
+ killed = _terminate_own_idle_in_tx(db_ops, logger)
+ if killed:
+ db_ops.commit()
+ _drop_schemas(db_ops, logger)
+ db_ops.commit()
+ return None
+
+ def stage_init_ods(db_ops: DatabaseOperations):
+ return _run_task(InitOdsSchemaTask(cfg, db_ops, None, logger), logger)
+
+ def stage_init_dwd(db_ops: DatabaseOperations):
+ return _run_task(InitDwdSchemaTask(cfg, db_ops, None, logger), logger)
+
+ def stage_manual_ingest(db_ops: DatabaseOperations):
+ logger.info("开始执行:MANUAL_INGEST(json_dir=%s)", json_dir)
+ return _run_task(ManualIngestTask(cfg, db_ops, None, logger), logger)
+
+ def stage_dwd_load(db_ops: DatabaseOperations):
+ logger.info("开始执行:DWD_LOAD_FROM_ODS")
+ return _run_task(DwdLoadTask(cfg, db_ops, None, logger), logger)
+
+ _run_stage_with_reconnect(cfg, logger, "DROP_SCHEMAS", stage_drop, max_attempts=3)
+ if args.stop_after == "DROP_SCHEMAS":
+ return 0
+ _run_stage_with_reconnect(cfg, logger, "INIT_ODS_SCHEMA", stage_init_ods, max_attempts=3)
+ if args.stop_after == "INIT_ODS_SCHEMA":
+ return 0
+ _run_stage_with_reconnect(cfg, logger, "INIT_DWD_SCHEMA", stage_init_dwd, max_attempts=3)
+ if args.stop_after == "INIT_DWD_SCHEMA":
+ return 0
+ _run_stage_with_reconnect(cfg, logger, "MANUAL_INGEST", stage_manual_ingest, max_attempts=5)
+ if args.stop_after == "MANUAL_INGEST":
+ return 0
+ _run_stage_with_reconnect(cfg, logger, "DWD_LOAD_FROM_ODS", stage_dwd_load, max_attempts=5)
+ if args.stop_after == "DWD_LOAD_FROM_ODS":
+ return 0
+
+ # 校验阶段复用一条新连接即可
+ _run_stage_with_reconnect(
+ cfg,
+ logger,
+ "BASIC_VALIDATE",
+ lambda db_ops: _basic_validate(db_ops, logger),
+ max_attempts=3,
+ )
+ if args.stop_after == "BASIC_VALIDATE":
+ return 0
+ return 0
+ finally:
+ if file_handler is not None:
+ try:
+ logging.getLogger().removeHandler(file_handler)
+ except Exception:
+ pass
+ try:
+ file_handler.close()
+ except Exception:
+ pass
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/rebuild_ods_from_json.py b/etl_billiards/scripts/rebuild_ods_from_json.py
index 0491afb..137a630 100644
--- a/etl_billiards/scripts/rebuild_ods_from_json.py
+++ b/etl_billiards/scripts/rebuild_ods_from_json.py
@@ -7,7 +7,7 @@
依赖环境变量:
PG_DSN PostgreSQL 连接串(必填)
PG_CONNECT_TIMEOUT 可选,秒,默认 10
- JSON_DOC_DIR 可选,JSON 目录,默认 C:\\dev\\LLTQ\\export\\test-json-doc
+ JSON_DOC_DIR 可选,JSON 目录,默认 export/test-json-doc
ODS_INCLUDE_FILES 可选,逗号分隔文件名(不含 .json)
ODS_DROP_SCHEMA_FIRST 可选,true/false,默认 true
"""
@@ -26,7 +26,7 @@ from psycopg2 import sql
from psycopg2.extras import Json, execute_values
-DEFAULT_JSON_DIR = r"C:\dev\LLTQ\export\test-json-doc"
+DEFAULT_JSON_DIR = "export/test-json-doc"
SPECIAL_LIST_PATHS: dict[str, tuple[str, ...]] = {
"assistant_accounts_master": ("data", "assistantInfos"),
"assistant_cancellation_records": ("data", "abolitionAssistants"),
diff --git a/etl_billiards/scripts/reload_ods_windowed.py b/etl_billiards/scripts/reload_ods_windowed.py
new file mode 100644
index 0000000..fc305e0
--- /dev/null
+++ b/etl_billiards/scripts/reload_ods_windowed.py
@@ -0,0 +1,224 @@
+# -*- coding: utf-8 -*-
+"""
+Reload ODS tasks by fixed time windows with optional sleep between windows.
+"""
+from __future__ import annotations
+
+import argparse
+import logging
+import subprocess
+import sys
+import time as time_mod
+from datetime import datetime, timedelta
+from pathlib import Path
+from zoneinfo import ZoneInfo
+
+from dateutil import parser as dtparser
+
+PROJECT_ROOT = Path(__file__).resolve().parents[1]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from config.settings import AppConfig
+from utils.windowing import split_window
+from utils.logging_utils import build_log_path, configure_logging
+
+MIN_RELOAD_WINDOW_DAYS = 30
+
+
+def _parse_dt(value: str, tz: ZoneInfo, *, is_end: bool) -> datetime:
+ raw = (value or "").strip()
+ if not raw:
+ raise ValueError("empty datetime")
+ has_time = any(ch in raw for ch in (":", "T"))
+ dt = dtparser.parse(raw)
+ if dt.tzinfo is None:
+ dt = dt.replace(tzinfo=tz)
+ else:
+ dt = dt.astimezone(tz)
+ if not has_time:
+ dt = dt.replace(hour=23 if is_end else 0, minute=59 if is_end else 0, second=59 if is_end else 0, microsecond=0)
+ return dt
+
+
+def _iter_windows(start: datetime, end: datetime, window_size: timedelta):
+ if window_size.total_seconds() <= 0:
+ raise ValueError("window_size must be > 0")
+ cur = start
+ while cur < end:
+ nxt = min(cur + window_size, end)
+ yield cur, nxt
+ cur = nxt
+
+
+def _run_task_window(
+ task_code: str,
+ window_start: datetime,
+ window_end: datetime,
+ api_page_size: int,
+ api_timeout: int,
+ logger: logging.Logger,
+ window_split_unit: str | None = "none",
+ window_compensation_hours: int | None = 0,
+) -> None:
+ cmd = [
+ sys.executable,
+ "-m",
+ "cli.main",
+ "--pipeline-flow",
+ "FULL",
+ "--tasks",
+ task_code,
+ "--window-start",
+ window_start.strftime("%Y-%m-%d %H:%M:%S"),
+ "--window-end",
+ window_end.strftime("%Y-%m-%d %H:%M:%S"),
+ "--force-window-override",
+ "--window-split-unit",
+ str(window_split_unit or "none"),
+ "--window-compensation-hours",
+ str(int(window_compensation_hours or 0)),
+ ]
+ if api_page_size > 0:
+ cmd += ["--api-page-size", str(api_page_size)]
+ if api_timeout > 0:
+ cmd += ["--api-timeout", str(api_timeout)]
+ logger.info(
+ "RUN_TASK task=%s window_start=%s window_end=%s",
+ task_code,
+ window_start.isoformat(),
+ window_end.isoformat(),
+ )
+ logger.debug("CMD %s", " ".join(cmd))
+ subprocess.run(cmd, check=True, cwd=str(PROJECT_ROOT))
+
+
+def main() -> int:
+ ap = argparse.ArgumentParser(description="Reload ODS tasks by window slices.")
+ ap.add_argument("--tasks", required=True, help="comma-separated ODS task codes")
+ ap.add_argument("--start", required=True, help="start datetime, e.g. 2025-07-01")
+ ap.add_argument("--end", default="", help="end datetime (default: now)")
+ ap.add_argument("--window-days", type=int, default=1, help="days per window (default: 1)")
+ ap.add_argument("--window-hours", type=int, default=0, help="hours per window (default: 0)")
+ ap.add_argument("--window-split-unit", default="", help="split unit (month/none), default from config")
+ ap.add_argument("--window-compensation-hours", type=int, default=None, help="window compensation hours, default from config")
+ ap.add_argument("--sleep-seconds", type=float, default=0, help="sleep seconds after each window")
+ ap.add_argument("--api-page-size", type=int, default=200, help="API page size override")
+ ap.add_argument("--api-timeout", type=int, default=20, help="API timeout seconds override")
+ ap.add_argument("--log-file", default="", help="log file path (default: logs/reload_ods_windowed_YYYYMMDD_HHMMSS.log)")
+ ap.add_argument("--log-dir", default="", help="log directory (default: logs)")
+ ap.add_argument("--log-level", default="INFO", help="log level (default: INFO)")
+ ap.add_argument("--no-log-console", action="store_true", help="disable console logging")
+ args = ap.parse_args()
+
+ log_dir = Path(args.log_dir) if args.log_dir else (PROJECT_ROOT / "logs")
+ log_file = Path(args.log_file) if args.log_file else build_log_path(log_dir, "reload_ods_windowed")
+ log_console = not args.no_log_console
+
+ with configure_logging(
+ "reload_ods_windowed",
+ log_file,
+ level=args.log_level,
+ console=log_console,
+ tee_std=True,
+ ) as logger:
+ cfg = AppConfig.load({})
+ tz = ZoneInfo(cfg.get("app.timezone", "Asia/Taipei"))
+
+ start = _parse_dt(args.start, tz, is_end=False)
+ end = datetime.now(tz) if not args.end else _parse_dt(args.end, tz, is_end=True)
+ window_days = int(args.window_days)
+ window_hours = int(args.window_hours)
+ split_unit = (args.window_split_unit or cfg.get("run.window_split.unit", "month") or "month").strip()
+ comp_hours = args.window_compensation_hours
+ if comp_hours is None:
+ comp_hours = cfg.get("run.window_split.compensation_hours", 0)
+
+ use_split = split_unit.lower() not in ("", "none", "off", "false", "0")
+ if use_split:
+ windows = split_window(
+ start,
+ end,
+ tz=tz,
+ split_unit=split_unit,
+ compensation_hours=comp_hours,
+ )
+ else:
+ min_hours = MIN_RELOAD_WINDOW_DAYS * 24
+ if window_hours > 0:
+ if window_hours < min_hours:
+ logger.warning(
+ "window_hours=%s too small; adjust to %s",
+ window_hours,
+ min_hours,
+ )
+ window_hours = min_hours
+ elif window_days < MIN_RELOAD_WINDOW_DAYS:
+ logger.warning(
+ "window_days=%s too small; adjust to %s",
+ window_days,
+ MIN_RELOAD_WINDOW_DAYS,
+ )
+ window_days = MIN_RELOAD_WINDOW_DAYS
+ adjusted = split_window(
+ start,
+ end,
+ tz=tz,
+ split_unit="none",
+ compensation_hours=comp_hours,
+ )
+ if adjusted:
+ start, end = adjusted[0]
+ window_size = timedelta(hours=window_hours) if window_hours > 0 else timedelta(days=window_days)
+ windows = list(_iter_windows(start, end, window_size))
+
+ if windows:
+ start, end = windows[0][0], windows[-1][1]
+
+ task_codes = [t.strip().upper() for t in args.tasks.split(",") if t.strip()]
+ if not task_codes:
+ raise SystemExit("no tasks specified")
+
+ logger.info(
+ "START range=%s~%s window_days=%s window_hours=%s split_unit=%s comp_hours=%s sleep=%.2f",
+ start.isoformat(),
+ end.isoformat(),
+ window_days,
+ window_hours,
+ split_unit,
+ comp_hours,
+ args.sleep_seconds,
+ )
+
+ for task_code in task_codes:
+ logger.info("TASK_START task=%s", task_code)
+ for window_start, window_end in windows:
+ start_ts = time_mod.monotonic()
+ _run_task_window(
+ task_code=task_code,
+ window_start=window_start,
+ window_end=window_end,
+ api_page_size=args.api_page_size,
+ api_timeout=args.api_timeout,
+ logger=logger,
+ window_split_unit="none",
+ window_compensation_hours=0,
+ )
+ elapsed = time_mod.monotonic() - start_ts
+ logger.info(
+ "WINDOW_DONE task=%s window_start=%s window_end=%s elapsed=%.2fs",
+ task_code,
+ window_start.isoformat(),
+ window_end.isoformat(),
+ elapsed,
+ )
+ if args.sleep_seconds > 0:
+ logger.debug("SLEEP seconds=%.2f", args.sleep_seconds)
+ time_mod.sleep(args.sleep_seconds)
+ logger.info("TASK_DONE task=%s", task_code)
+
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/scripts/test_db_performance.py b/etl_billiards/scripts/test_db_performance.py
new file mode 100644
index 0000000..d30e61d
--- /dev/null
+++ b/etl_billiards/scripts/test_db_performance.py
@@ -0,0 +1,267 @@
+# -*- coding: utf-8 -*-
+"""PostgreSQL connection performance test (ASCII-only output)."""
+from __future__ import annotations
+
+import argparse
+import math
+import os
+import statistics
+import sys
+import time
+from typing import Dict, Iterable, List
+
+from psycopg2.extensions import make_dsn, parse_dsn
+
+PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
+if PROJECT_ROOT not in sys.path:
+ sys.path.insert(0, PROJECT_ROOT)
+
+from database.connection import DatabaseConnection
+
+
+def _load_env() -> Dict[str, str]:
+ env: Dict[str, str] = {}
+ try:
+ from config.env_parser import _load_dotenv_values
+ except Exception:
+ _load_dotenv_values = None
+ if _load_dotenv_values:
+ try:
+ env.update(_load_dotenv_values())
+ except Exception:
+ pass
+ env.update(os.environ)
+ return env
+
+
+def _apply_dsn_overrides(dsn: str, host: str | None, port: int | None) -> str:
+ overrides = {}
+ if host:
+ overrides["host"] = host
+ if port:
+ overrides["port"] = str(port)
+ if not overrides:
+ return dsn
+ return make_dsn(dsn, **overrides)
+
+
+def _build_dsn_from_env(
+ host: str,
+ port: int,
+ user: str | None,
+ password: str | None,
+ dbname: str | None,
+) -> str | None:
+ if not user or not dbname:
+ return None
+ params = {
+ "host": host,
+ "port": str(port),
+ "user": user,
+ "dbname": dbname,
+ }
+ if password:
+ params["password"] = password
+ return make_dsn("", **params)
+
+
+def _safe_dsn_summary(dsn: str, host: str | None, port: int | None) -> str:
+ try:
+ info = parse_dsn(dsn)
+ except Exception:
+ info = {}
+ if host:
+ info["host"] = host
+ if port:
+ info["port"] = str(port)
+ info.pop("password", None)
+ if not info:
+ return "dsn=(hidden)"
+ items = " ".join(f"{k}={info[k]}" for k in sorted(info.keys()))
+ return items
+
+
+def _percentile(values: List[float], pct: float) -> float:
+ if not values:
+ return 0.0
+ ordered = sorted(values)
+ if len(ordered) == 1:
+ return ordered[0]
+ rank = (len(ordered) - 1) * (pct / 100.0)
+ low = int(math.floor(rank))
+ high = int(math.ceil(rank))
+ if low == high:
+ return ordered[low]
+ return ordered[low] + (ordered[high] - ordered[low]) * (rank - low)
+
+
+def _format_stats(label: str, values: Iterable[float]) -> str:
+ data = list(values)
+ if not data:
+ return f"{label}: no samples"
+ avg = statistics.mean(data)
+ stdev = statistics.stdev(data) if len(data) > 1 else 0.0
+ return (
+ f"{label}: count={len(data)} "
+ f"min={min(data):.2f}ms avg={avg:.2f}ms "
+ f"p50={_percentile(data, 50):.2f}ms "
+ f"p95={_percentile(data, 95):.2f}ms "
+ f"max={max(data):.2f}ms stdev={stdev:.2f}ms"
+ )
+
+
+def parse_args() -> argparse.Namespace:
+ parser = argparse.ArgumentParser(description="PostgreSQL connection performance test")
+ parser.add_argument("--dsn", help="Override PG_DSN/TEST_DB_DSN/.env value")
+ parser.add_argument(
+ "--host",
+ default="100.64.0.4",
+ help="Override host in DSN (default: 100.64.0.4)",
+ )
+ parser.add_argument("--port", type=int, help="Override port in DSN")
+ parser.add_argument("--user", help="User when building DSN from PG_* env")
+ parser.add_argument("--password", help="Password when building DSN from PG_* env")
+ parser.add_argument("--dbname", help="Database name when building DSN from PG_* env")
+ parser.add_argument("--rounds", type=int, default=20, help="Measured connection rounds")
+ parser.add_argument("--warmup", type=int, default=2, help="Warmup rounds (not recorded)")
+ parser.add_argument("--query", default="SELECT 1", help="SQL to run after connect")
+ parser.add_argument(
+ "--query-repeat",
+ type=int,
+ default=1,
+ help="Query repetitions per connection (0 to skip)",
+ )
+ parser.add_argument(
+ "--connect-timeout",
+ type=int,
+ default=10,
+ help="connect_timeout seconds (capped at 20, default: 10)",
+ )
+ parser.add_argument(
+ "--statement-timeout-ms",
+ type=int,
+ help="Optional statement_timeout applied per connection",
+ )
+ parser.add_argument(
+ "--sleep-ms",
+ type=int,
+ default=0,
+ help="Sleep between rounds in milliseconds",
+ )
+ parser.add_argument(
+ "--continue-on-error",
+ action="store_true",
+ help="Continue even if a round fails",
+ )
+ parser.add_argument("--verbose", action="store_true", help="Print per-round timings")
+ return parser.parse_args()
+
+
+def _run_round(
+ dsn: str,
+ timeout: int,
+ query: str,
+ query_repeat: int,
+ session: Dict[str, int] | None,
+) -> tuple[float, List[float]]:
+ start = time.perf_counter()
+ conn = DatabaseConnection(dsn, connect_timeout=timeout, session=session)
+ connect_ms = (time.perf_counter() - start) * 1000.0
+ query_times: List[float] = []
+ try:
+ for _ in range(query_repeat):
+ q_start = time.perf_counter()
+ conn.query(query)
+ query_times.append((time.perf_counter() - q_start) * 1000.0)
+ return connect_ms, query_times
+ finally:
+ try:
+ conn.rollback()
+ except Exception:
+ pass
+ conn.close()
+
+
+def main() -> int:
+ args = parse_args()
+ if args.rounds < 0 or args.warmup < 0 or args.query_repeat < 0:
+ print("rounds/warmup/query-repeat must be >= 0", file=sys.stderr)
+ return 2
+ env = _load_env()
+
+ dsn = args.dsn or env.get("PG_DSN") or env.get("TEST_DB_DSN")
+ host = args.host
+ port = args.port
+
+ if not dsn:
+ user = args.user or env.get("PG_USER")
+ password = args.password if args.password is not None else env.get("PG_PASSWORD")
+ dbname = args.dbname or env.get("PG_NAME")
+ try:
+ resolved_port = port or int(env.get("PG_PORT", "5432"))
+ except ValueError:
+ resolved_port = port or 5432
+ dsn = _build_dsn_from_env(host, resolved_port, user, password, dbname)
+ if not dsn:
+ print(
+ "Missing DSN. Provide --dsn or set PG_DSN/TEST_DB_DSN, or PG_USER + PG_NAME.",
+ file=sys.stderr,
+ )
+ return 2
+ dsn = _apply_dsn_overrides(dsn, host, port)
+
+ timeout = max(1, min(int(args.connect_timeout), 20))
+ session = None
+ if args.statement_timeout_ms is not None:
+ session = {"statement_timeout_ms": int(args.statement_timeout_ms)}
+
+ print("Target:", _safe_dsn_summary(dsn, host, port))
+ print(
+ f"Rounds: {args.rounds} (warmup {args.warmup}), "
+ f"query_repeat={args.query_repeat}, timeout={timeout}s"
+ )
+ if args.query_repeat > 0:
+ print("Query:", args.query)
+
+ connect_times: List[float] = []
+ query_times: List[float] = []
+ failures: List[str] = []
+
+ total = args.warmup + args.rounds
+ for idx in range(total):
+ is_warmup = idx < args.warmup
+ try:
+ c_ms, q_times = _run_round(
+ dsn, timeout, args.query, args.query_repeat, session
+ )
+ if not is_warmup:
+ connect_times.append(c_ms)
+ query_times.extend(q_times)
+ if args.verbose:
+ tag = "warmup" if is_warmup else "sample"
+ q_msg = ""
+ if args.query_repeat > 0:
+ q_avg = statistics.mean(q_times) if q_times else 0.0
+ q_msg = f", query_avg={q_avg:.2f}ms"
+ print(f"[{tag} {idx + 1}/{total}] connect={c_ms:.2f}ms{q_msg}")
+ except Exception as exc:
+ msg = f"round {idx + 1}: {exc}"
+ failures.append(msg)
+ print("Failure:", msg, file=sys.stderr)
+ if not args.continue_on_error:
+ break
+ if args.sleep_ms > 0:
+ time.sleep(args.sleep_ms / 1000.0)
+
+ if connect_times:
+ print(_format_stats("Connect", connect_times))
+ if args.query_repeat > 0:
+ print(_format_stats("Query", query_times))
+ if failures:
+ print(f"Failures: {len(failures)}", file=sys.stderr)
+ return 1
+ return 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())
diff --git a/etl_billiards/tasks/base_task.py b/etl_billiards/tasks/base_task.py
index a785528..988c176 100644
--- a/etl_billiards/tasks/base_task.py
+++ b/etl_billiards/tasks/base_task.py
@@ -5,6 +5,9 @@ from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
+from dateutil import parser as dtparser
+
+from utils.windowing import build_window_segments, calc_window_minutes
@dataclass(frozen=True)
@@ -49,35 +52,72 @@ class BaseTask:
# ------------------------------------------------------------------ 主流程
def execute(self, cursor_data: dict | None = None) -> dict:
"""统一 orchestrate Extract → Transform → Load"""
- context = self._build_context(cursor_data)
+ base_context = self._build_context(cursor_data)
task_code = self.get_task_code()
- self.logger.info(
- "%s: 开始执行,窗口[%s ~ %s]",
- task_code,
- context.window_start,
- context.window_end,
+ segments = build_window_segments(
+ self.config,
+ base_context.window_start,
+ base_context.window_end,
+ tz=self.tz,
+ override_only=True,
)
+ if not segments:
+ segments = [(base_context.window_start, base_context.window_end)]
- try:
- extracted = self.extract(context)
- transformed = self.transform(extracted, context)
- counts = self.load(transformed, context) or {}
- self.db.commit()
- except Exception:
- self.db.rollback()
- self.logger.error("%s: 执行失败", task_code, exc_info=True)
- raise
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info("%s: 窗口拆分为 %s 段", task_code, total_segments)
- result = self._build_result("SUCCESS", counts)
+ total_counts: dict = {}
+ segment_results: list[dict] = []
+
+ for idx, (window_start, window_end) in enumerate(segments, start=1):
+ context = self._build_context_for_window(window_start, window_end, cursor_data)
+ self.logger.info(
+ "%s: 开始执行(%s/%s),窗口[%s ~ %s]",
+ task_code,
+ idx,
+ total_segments,
+ context.window_start,
+ context.window_end,
+ )
+
+ try:
+ extracted = self.extract(context)
+ transformed = self.transform(extracted, context)
+ counts = self.load(transformed, context) or {}
+ self.db.commit()
+ except Exception:
+ self.db.rollback()
+ self.logger.error("%s: 执行失败", task_code, exc_info=True)
+ raise
+
+ self._accumulate_counts(total_counts, counts)
+ if total_segments > 1:
+ segment_results.append(
+ {
+ "window": {
+ "start": context.window_start,
+ "end": context.window_end,
+ "minutes": context.window_minutes,
+ },
+ "counts": counts,
+ }
+ )
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+ result = self._build_result("SUCCESS", total_counts)
result["window"] = {
- "start": context.window_start,
- "end": context.window_end,
- "minutes": context.window_minutes,
+ "start": overall_start,
+ "end": overall_end,
+ "minutes": calc_window_minutes(overall_start, overall_end),
}
+ if segment_results:
+ result["segments"] = segment_results
self.logger.info("%s: 完成,统计=%s", task_code, result["counts"])
return result
- # ------------------------------------------------------------------ 辅助方法
def _build_context(self, cursor_data: dict | None) -> TaskContext:
window_start, window_end, window_minutes = self._get_time_window(cursor_data)
return TaskContext(
@@ -88,10 +128,63 @@ class BaseTask:
cursor=cursor_data,
)
+ def _build_context_for_window(
+ self,
+ window_start: datetime,
+ window_end: datetime,
+ cursor_data: dict | None,
+ ) -> TaskContext:
+ return TaskContext(
+ store_id=self.config.get("app.store_id"),
+ window_start=window_start,
+ window_end=window_end,
+ window_minutes=calc_window_minutes(window_start, window_end),
+ cursor=cursor_data,
+ )
+
+ @staticmethod
+ def _accumulate_counts(total: dict, current: dict) -> dict:
+ for key, value in (current or {}).items():
+ if isinstance(value, (int, float)):
+ total[key] = (total.get(key) or 0) + value
+ else:
+ total.setdefault(key, value)
+ return total
+
def _get_time_window(self, cursor_data: dict = None) -> tuple:
"""计算时间窗口"""
now = datetime.now(self.tz)
+ override_start = self.config.get("run.window_override.start")
+ override_end = self.config.get("run.window_override.end")
+ if override_start or override_end:
+ if not (override_start and override_end):
+ raise ValueError("run.window_override.start/end 需要同时提供")
+
+ window_start = override_start
+ if isinstance(window_start, str):
+ window_start = dtparser.parse(window_start)
+ if isinstance(window_start, datetime) and window_start.tzinfo is None:
+ window_start = window_start.replace(tzinfo=self.tz)
+ elif isinstance(window_start, datetime):
+ window_start = window_start.astimezone(self.tz)
+
+ window_end = override_end
+ if isinstance(window_end, str):
+ window_end = dtparser.parse(window_end)
+ if isinstance(window_end, datetime) and window_end.tzinfo is None:
+ window_end = window_end.replace(tzinfo=self.tz)
+ elif isinstance(window_end, datetime):
+ window_end = window_end.astimezone(self.tz)
+
+ if not isinstance(window_start, datetime) or not isinstance(window_end, datetime):
+ raise ValueError("run.window_override.start/end 解析失败")
+ if window_end <= window_start:
+ raise ValueError("run.window_override.end 必须大于 start")
+
+ window_minutes = max(1, int((window_end - window_start).total_seconds() // 60))
+ return window_start, window_end, window_minutes
+
idle_start = self.config.get("run.idle_window.start", "04:00")
idle_end = self.config.get("run.idle_window.end", "16:00")
is_idle = self._is_in_idle_window(now, idle_start, idle_end)
diff --git a/etl_billiards/tasks/check_cutoff_task.py b/etl_billiards/tasks/check_cutoff_task.py
new file mode 100644
index 0000000..b64a176
--- /dev/null
+++ b/etl_billiards/tasks/check_cutoff_task.py
@@ -0,0 +1,125 @@
+# -*- coding: utf-8 -*-
+"""Task: report last successful cursor cutoff times from etl_admin."""
+
+from __future__ import annotations
+
+from typing import Any
+
+from .base_task import BaseTask
+
+
+class CheckCutoffTask(BaseTask):
+ """Report per-task cursor cutoff times (etl_admin.etl_cursor.last_end)."""
+
+ def get_task_code(self) -> str:
+ return "CHECK_CUTOFF"
+
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ store_id = int(self.config.get("app.store_id"))
+ filter_codes = self.config.get("run.cutoff_task_codes") or None
+ if isinstance(filter_codes, str):
+ filter_codes = [c.strip().upper() for c in filter_codes.split(",") if c.strip()]
+
+ sql = """
+ SELECT
+ t.task_code,
+ c.last_start,
+ c.last_end,
+ c.last_id,
+ c.last_run_id,
+ c.updated_at
+ FROM etl_admin.etl_task t
+ LEFT JOIN etl_admin.etl_cursor c
+ ON c.task_id = t.task_id AND c.store_id = t.store_id
+ WHERE t.store_id = %s
+ AND t.enabled = TRUE
+ ORDER BY t.task_code
+ """
+ rows = self.db.query(sql, (store_id,))
+
+ if filter_codes:
+ wanted = {str(c).upper() for c in filter_codes}
+ rows = [r for r in rows if str(r.get("task_code", "")).upper() in wanted]
+
+ def _ts(v: Any) -> str:
+ return "-" if not v else str(v)
+
+ self.logger.info("截止时间检查: 门店ID=%s 启用任务数=%s", store_id, len(rows))
+ for r in rows:
+ self.logger.info(
+ "截止时间检查: %-24s 结束时间=%s 开始时间=%s 运行ID=%s",
+ str(r.get("task_code") or ""),
+ _ts(r.get("last_end")),
+ _ts(r.get("last_start")),
+ _ts(r.get("last_run_id")),
+ )
+
+ cutoff_candidates = [
+ r.get("last_end")
+ for r in rows
+ if r.get("last_end") is not None and not str(r.get("task_code", "")).upper().startswith("INIT_")
+ ]
+ cutoff = min(cutoff_candidates) if cutoff_candidates else None
+ self.logger.info("截止时间检查: 总体截止时间(最小结束时间,排除INIT_*)=%s", _ts(cutoff))
+
+ ods_fetched = self._probe_ods_fetched_at(store_id)
+ if ods_fetched:
+ non_null = [v["max_fetched_at"] for v in ods_fetched.values() if v.get("max_fetched_at") is not None]
+ ods_cutoff = min(non_null) if non_null else None
+ self.logger.info("截止时间检查: ODS截止时间(最小抓取时间)=%s", _ts(ods_cutoff))
+ worst = sorted(
+ ((k, v.get("max_fetched_at")) for k, v in ods_fetched.items()),
+ key=lambda kv: (kv[1] is None, kv[1]),
+ )[:8]
+ for table, mx in worst:
+ self.logger.info("截止时间检查: ODS表=%s 最大抓取时间=%s", table, _ts(mx))
+
+ dw_checks = self._probe_dw_time_columns()
+ for name, value in dw_checks.items():
+ self.logger.info("截止时间检查: %s=%s", name, _ts(value))
+
+ return {
+ "status": "SUCCESS",
+ "counts": {"fetched": len(rows), "inserted": 0, "updated": 0, "skipped": 0, "errors": 0},
+ "window": None,
+ "request_params": {"store_id": store_id, "filter_task_codes": filter_codes or []},
+ "report": {
+ "rows": rows,
+ "overall_cutoff": cutoff,
+ "ods_fetched_at": ods_fetched,
+ "dw_max_times": dw_checks,
+ },
+ }
+
+ def _probe_ods_fetched_at(self, store_id: int) -> dict[str, dict[str, Any]]:
+ try:
+ from tasks.dwd_load_task import DwdLoadTask # local import to avoid circulars
+ except Exception:
+ return {}
+
+ ods_tables = sorted({str(t) for t in DwdLoadTask.TABLE_MAP.values() if str(t).startswith("billiards_ods.")})
+ results: dict[str, dict[str, Any]] = {}
+ for table in ods_tables:
+ try:
+ row = self.db.query(f"SELECT MAX(fetched_at) AS mx, COUNT(*) AS cnt FROM {table}")[0]
+ results[table] = {"max_fetched_at": row.get("mx"), "count": row.get("cnt")}
+ except Exception as exc: # noqa: BLE001
+ results[table] = {"max_fetched_at": None, "count": None, "error": str(exc)}
+ return results
+
+ def _probe_dw_time_columns(self) -> dict[str, Any]:
+ checks: dict[str, Any] = {}
+ probes = {
+ "DWD.max_settlement_pay_time": "SELECT MAX(pay_time) AS mx FROM billiards_dwd.dwd_settlement_head",
+ "DWD.max_payment_pay_time": "SELECT MAX(pay_time) AS mx FROM billiards_dwd.dwd_payment",
+ "DWD.max_refund_pay_time": "SELECT MAX(pay_time) AS mx FROM billiards_dwd.dwd_refund",
+ "DWS.max_order_date": "SELECT MAX(order_date) AS mx FROM billiards_dws.dws_order_summary",
+ "DWS.max_updated_at": "SELECT MAX(updated_at) AS mx FROM billiards_dws.dws_order_summary",
+ }
+ for name, sql2 in probes.items():
+ try:
+ row = self.db.query(sql2)[0]
+ checks[name] = row.get("mx")
+ except Exception as exc: # noqa: BLE001
+ checks[name] = f"ERROR: {exc}"
+ return checks
diff --git a/etl_billiards/tasks/data_integrity_task.py b/etl_billiards/tasks/data_integrity_task.py
new file mode 100644
index 0000000..bba9b1d
--- /dev/null
+++ b/etl_billiards/tasks/data_integrity_task.py
@@ -0,0 +1,212 @@
+# -*- coding: utf-8 -*-
+"""Data integrity task that checks API -> ODS -> DWD completeness."""
+from __future__ import annotations
+
+from datetime import datetime
+from zoneinfo import ZoneInfo
+
+from dateutil import parser as dtparser
+
+import json
+from pathlib import Path
+from utils.windowing import build_window_segments, calc_window_minutes
+from .base_task import BaseTask
+from quality.integrity_checker import (
+ IntegrityWindow,
+ compute_last_etl_end,
+ run_integrity_history,
+ run_integrity_window,
+)
+
+
+class DataIntegrityTask(BaseTask):
+ """Check data completeness across API -> ODS -> DWD."""
+
+ def get_task_code(self) -> str:
+ return "DATA_INTEGRITY_CHECK"
+
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ tz = ZoneInfo(self.config.get("app.timezone", "Asia/Taipei"))
+ mode = str(self.config.get("integrity.mode", "history") or "history").lower()
+ include_dimensions = bool(self.config.get("integrity.include_dimensions", False))
+ task_codes = str(self.config.get("integrity.ods_task_codes", "") or "").strip()
+ auto_backfill = bool(self.config.get("integrity.auto_backfill", False))
+
+ # 检测是否通过 CLI 传入了时间窗口参数(window_override)
+ # 如果有,自动切换到 window 模式
+ window_override_start = self.config.get("run.window_override.start")
+ window_override_end = self.config.get("run.window_override.end")
+ if window_override_start or window_override_end:
+ self.logger.info(
+ "检测到 CLI 时间窗口参数,自动切换到 window 模式: %s ~ %s",
+ window_override_start, window_override_end
+ )
+ mode = "window"
+
+ if mode == "window":
+ base_start, base_end, _ = self._get_time_window(cursor_data)
+ segments = build_window_segments(
+ self.config,
+ base_start,
+ base_end,
+ tz=tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(base_start, base_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info("数据完整性检查: 分段执行 共%s段", total_segments)
+
+ window_reports = []
+ total_missing = 0
+ total_errors = 0
+ for idx, (seg_start, seg_end) in enumerate(segments, start=1):
+ window = IntegrityWindow(
+ start=seg_start,
+ end=seg_end,
+ label=f"segment_{idx}",
+ granularity="window",
+ )
+ payload = run_integrity_window(
+ cfg=self.config,
+ window=window,
+ include_dimensions=include_dimensions,
+ task_codes=task_codes,
+ logger=self.logger,
+ write_report=False,
+ window_split_unit="none",
+ window_compensation_hours=0,
+ )
+ window_reports.append(payload)
+ total_missing += int(payload.get("api_to_ods", {}).get("total_missing") or 0)
+ total_errors += int(payload.get("api_to_ods", {}).get("total_errors") or 0)
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+ report = {
+ "mode": "window",
+ "window": {
+ "start": overall_start.isoformat(),
+ "end": overall_end.isoformat(),
+ "segments": total_segments,
+ },
+ "windows": window_reports,
+ "api_to_ods": {
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ },
+ "total_missing": total_missing,
+ "total_errors": total_errors,
+ "generated_at": datetime.now(tz).isoformat(),
+ }
+ report_path = self._write_report(report, "data_integrity_window")
+ report["report_path"] = report_path
+
+ missing_count = int(total_missing or 0)
+ counts = {
+ "missing": missing_count,
+ "errors": int(total_errors or 0),
+ }
+
+ # ????
+ backfill_result = None
+ if auto_backfill and missing_count > 0:
+ backfill_result = self._run_backfill(base_start, base_end, task_codes)
+ counts["backfilled"] = backfill_result.get("backfilled", 0)
+
+ return {
+ "status": "SUCCESS",
+ "counts": counts,
+ "window": {
+ "start": overall_start,
+ "end": overall_end,
+ "minutes": calc_window_minutes(overall_start, overall_end),
+ },
+ "report_path": report_path,
+ "backfill_result": backfill_result,
+ }
+
+ history_start = str(self.config.get("integrity.history_start", "2025-07-01") or "2025-07-01")
+ history_end = str(self.config.get("integrity.history_end", "") or "").strip()
+ start_dt = dtparser.parse(history_start)
+ if start_dt.tzinfo is None:
+ start_dt = start_dt.replace(tzinfo=tz)
+ else:
+ start_dt = start_dt.astimezone(tz)
+
+ if history_end:
+ end_dt = dtparser.parse(history_end)
+ if end_dt.tzinfo is None:
+ end_dt = end_dt.replace(tzinfo=tz)
+ else:
+ end_dt = end_dt.astimezone(tz)
+ else:
+ end_dt = compute_last_etl_end(self.config) or datetime.now(tz)
+
+ report = run_integrity_history(
+ cfg=self.config,
+ start_dt=start_dt,
+ end_dt=end_dt,
+ include_dimensions=include_dimensions,
+ task_codes=task_codes,
+ logger=self.logger,
+ write_report=True,
+ )
+ missing_count = int(report.get("total_missing") or 0)
+ counts = {
+ "missing": missing_count,
+ "errors": int(report.get("total_errors") or 0),
+ }
+
+ # 自动补全
+ backfill_result = None
+ if auto_backfill and missing_count > 0:
+ backfill_result = self._run_backfill(start_dt, end_dt, task_codes)
+ counts["backfilled"] = backfill_result.get("backfilled", 0)
+
+ return {
+ "status": "SUCCESS",
+ "counts": counts,
+ "window": {
+ "start": start_dt,
+ "end": end_dt,
+ "minutes": int((end_dt - start_dt).total_seconds() // 60) if end_dt > start_dt else 0,
+ },
+ "report_path": report.get("report_path"),
+ "backfill_result": backfill_result,
+ }
+
+ def _write_report(self, report: dict, prefix: str) -> str:
+ root = Path(__file__).resolve().parents[1]
+ stamp = datetime.now(self.tz).strftime("%Y%m%d_%H%M%S")
+ path = root / "reports" / f"{prefix}_{stamp}.json"
+ path.parent.mkdir(parents=True, exist_ok=True)
+ path.write_text(json.dumps(report, ensure_ascii=False, indent=2) + "\n", encoding="utf-8")
+ return str(path)
+
+ def _run_backfill(self, start_dt: datetime, end_dt: datetime, task_codes: str) -> dict:
+ """运行数据补全"""
+ self.logger.info("自动补全开始 起始=%s 结束=%s", start_dt, end_dt)
+ try:
+ from scripts.backfill_missing_data import run_backfill
+ result = run_backfill(
+ cfg=self.config,
+ start=start_dt,
+ end=end_dt,
+ task_codes=task_codes or None,
+ dry_run=False,
+ page_size=200,
+ chunk_size=500,
+ logger=self.logger,
+ )
+ self.logger.info(
+ "自动补全完成 已补全=%s 错误数=%s",
+ result.get("backfilled", 0),
+ result.get("errors", 0),
+ )
+ return result
+ except Exception as exc:
+ self.logger.exception("自动补全失败")
+ return {"backfilled": 0, "errors": 1, "error": str(exc)}
diff --git a/etl_billiards/tasks/dwd_load_task.py b/etl_billiards/tasks/dwd_load_task.py
new file mode 100644
index 0000000..f7e841c
--- /dev/null
+++ b/etl_billiards/tasks/dwd_load_task.py
@@ -0,0 +1,1325 @@
+# -*- coding: utf-8 -*-
+"""DWD 装载任务:从 ODS 增量写入 DWD(维度 SCD2,事实按时间增量)。"""
+from __future__ import annotations
+
+import time
+from datetime import datetime
+from typing import Any, Dict, Iterable, List, Sequence
+
+from psycopg2.extras import RealDictCursor, execute_batch, execute_values
+
+from .base_task import BaseTask, TaskContext
+
+
+class DwdLoadTask(BaseTask):
+ """负责 DWD 装载:维度表做 SCD2 合并,事实表按时间增量写入。"""
+
+ # DWD -> ODS 表映射(ODS 表名已与示例 JSON 前缀统一)
+ TABLE_MAP: dict[str, str] = {
+ # 维度
+ # 门店:改用台费流水中的 siteprofile 快照,补齐 org/地址等字段
+ "billiards_dwd.dim_site": "billiards_ods.table_fee_transactions",
+ "billiards_dwd.dim_site_ex": "billiards_ods.table_fee_transactions",
+ "billiards_dwd.dim_table": "billiards_ods.site_tables_master",
+ "billiards_dwd.dim_table_ex": "billiards_ods.site_tables_master",
+ "billiards_dwd.dim_assistant": "billiards_ods.assistant_accounts_master",
+ "billiards_dwd.dim_assistant_ex": "billiards_ods.assistant_accounts_master",
+ "billiards_dwd.dim_member": "billiards_ods.member_profiles",
+ "billiards_dwd.dim_member_ex": "billiards_ods.member_profiles",
+ "billiards_dwd.dim_member_card_account": "billiards_ods.member_stored_value_cards",
+ "billiards_dwd.dim_member_card_account_ex": "billiards_ods.member_stored_value_cards",
+ "billiards_dwd.dim_tenant_goods": "billiards_ods.tenant_goods_master",
+ "billiards_dwd.dim_tenant_goods_ex": "billiards_ods.tenant_goods_master",
+ "billiards_dwd.dim_store_goods": "billiards_ods.store_goods_master",
+ "billiards_dwd.dim_store_goods_ex": "billiards_ods.store_goods_master",
+ "billiards_dwd.dim_goods_category": "billiards_ods.stock_goods_category_tree",
+ "billiards_dwd.dim_groupbuy_package": "billiards_ods.group_buy_packages",
+ "billiards_dwd.dim_groupbuy_package_ex": "billiards_ods.group_buy_packages",
+ # 事实
+ "billiards_dwd.dwd_settlement_head": "billiards_ods.settlement_records",
+ "billiards_dwd.dwd_settlement_head_ex": "billiards_ods.settlement_records",
+ "billiards_dwd.dwd_table_fee_log": "billiards_ods.table_fee_transactions",
+ "billiards_dwd.dwd_table_fee_log_ex": "billiards_ods.table_fee_transactions",
+ "billiards_dwd.dwd_table_fee_adjust": "billiards_ods.table_fee_discount_records",
+ "billiards_dwd.dwd_table_fee_adjust_ex": "billiards_ods.table_fee_discount_records",
+ "billiards_dwd.dwd_store_goods_sale": "billiards_ods.store_goods_sales_records",
+ "billiards_dwd.dwd_store_goods_sale_ex": "billiards_ods.store_goods_sales_records",
+ "billiards_dwd.dwd_assistant_service_log": "billiards_ods.assistant_service_records",
+ "billiards_dwd.dwd_assistant_service_log_ex": "billiards_ods.assistant_service_records",
+ "billiards_dwd.dwd_assistant_trash_event": "billiards_ods.assistant_cancellation_records",
+ "billiards_dwd.dwd_assistant_trash_event_ex": "billiards_ods.assistant_cancellation_records",
+ "billiards_dwd.dwd_member_balance_change": "billiards_ods.member_balance_changes",
+ "billiards_dwd.dwd_member_balance_change_ex": "billiards_ods.member_balance_changes",
+ "billiards_dwd.dwd_groupbuy_redemption": "billiards_ods.group_buy_redemption_records",
+ "billiards_dwd.dwd_groupbuy_redemption_ex": "billiards_ods.group_buy_redemption_records",
+ "billiards_dwd.dwd_platform_coupon_redemption": "billiards_ods.platform_coupon_redemption_records",
+ "billiards_dwd.dwd_platform_coupon_redemption_ex": "billiards_ods.platform_coupon_redemption_records",
+ "billiards_dwd.dwd_recharge_order": "billiards_ods.recharge_settlements",
+ "billiards_dwd.dwd_recharge_order_ex": "billiards_ods.recharge_settlements",
+ "billiards_dwd.dwd_payment": "billiards_ods.payment_transactions",
+ "billiards_dwd.dwd_refund": "billiards_ods.refund_transactions",
+ "billiards_dwd.dwd_refund_ex": "billiards_ods.refund_transactions",
+ }
+
+ SCD_COLS = {"scd2_start_time", "scd2_end_time", "scd2_is_current", "scd2_version"}
+ # 增量/窗口过滤优先使用业务时间;fetched_at(入库时间)放最后,避免回溯窗口被“当前入库时间”干扰。
+ FACT_ORDER_CANDIDATES = [
+ "pay_time",
+ "create_time",
+ "update_time",
+ "occur_time",
+ "settle_time",
+ "start_use_time",
+ "fetched_at",
+ ]
+ # 对于会出现“回补旧记录”的事实表,额外补齐缺失主键记录
+ FACT_MISSING_FILL_TABLES = {
+ "billiards_dwd.dwd_assistant_service_log",
+ }
+
+ # 特殊列映射:dwd 列名 -> 源列表达式(可选 CAST)
+ FACT_MAPPINGS: dict[str, list[tuple[str, str, str | None]]] = {
+ # 维度表(补齐主键/字段差异)
+ "billiards_dwd.dim_site": [
+ ("org_id", "siteprofile->>'org_id'", None),
+ ("shop_name", "siteprofile->>'shop_name'", None),
+ ("site_label", "siteprofile->>'site_label'", None),
+ ("full_address", "siteprofile->>'full_address'", None),
+ ("address", "siteprofile->>'address'", None),
+ ("longitude", "siteprofile->>'longitude'", "numeric"),
+ ("latitude", "siteprofile->>'latitude'", "numeric"),
+ ("tenant_site_region_id", "siteprofile->>'tenant_site_region_id'", None),
+ ("business_tel", "siteprofile->>'business_tel'", None),
+ ("site_type", "siteprofile->>'site_type'", None),
+ ("shop_status", "siteprofile->>'shop_status'", None),
+ ("tenant_id", "siteprofile->>'tenant_id'", None),
+ ],
+ "billiards_dwd.dim_site_ex": [
+ ("auto_light", "siteprofile->>'auto_light'", None),
+ ("attendance_enabled", "siteprofile->>'attendance_enabled'", None),
+ ("attendance_distance", "siteprofile->>'attendance_distance'", None),
+ ("prod_env", "siteprofile->>'prod_env'", None),
+ ("light_status", "siteprofile->>'light_status'", None),
+ ("light_type", "siteprofile->>'light_type'", None),
+ ("light_token", "siteprofile->>'light_token'", None),
+ ("address", "siteprofile->>'address'", None),
+ ("avatar", "siteprofile->>'avatar'", None),
+ ("wifi_name", "siteprofile->>'wifi_name'", None),
+ ("wifi_password", "siteprofile->>'wifi_password'", None),
+ ("customer_service_qrcode", "siteprofile->>'customer_service_qrcode'", None),
+ ("customer_service_wechat", "siteprofile->>'customer_service_wechat'", None),
+ ("fixed_pay_qrcode", "siteprofile->>'fixed_pay_qrCode'", None),
+ ("longitude", "siteprofile->>'longitude'", "numeric"),
+ ("latitude", "siteprofile->>'latitude'", "numeric"),
+ ("tenant_site_region_id", "siteprofile->>'tenant_site_region_id'", None),
+ ("site_type", "siteprofile->>'site_type'", None),
+ ("site_label", "siteprofile->>'site_label'", None),
+ ("shop_status", "siteprofile->>'shop_status'", None),
+ ("create_time", "siteprofile->>'create_time'", "timestamptz"),
+ ("update_time", "siteprofile->>'update_time'", "timestamptz"),
+ ],
+ "billiards_dwd.dim_table": [
+ ("table_id", "id", None),
+ ("site_table_area_name", "areaname", None),
+ ("tenant_table_area_id", "site_table_area_id", None),
+ ],
+ "billiards_dwd.dim_table_ex": [
+ ("table_id", "id", None),
+ ("table_cloth_use_time", "table_cloth_use_time", None),
+ ],
+ "billiards_dwd.dim_assistant": [("assistant_id", "id", None), ("user_id", "staff_id", None)],
+ "billiards_dwd.dim_assistant_ex": [
+ ("assistant_id", "id", None),
+ ("introduce", "introduce", None),
+ ("group_name", "group_name", None),
+ ("light_equipment_id", "light_equipment_id", None),
+ ],
+ "billiards_dwd.dim_member": [("member_id", "id", None)],
+ "billiards_dwd.dim_member_ex": [
+ ("member_id", "id", None),
+ ("register_site_name", "site_name", None),
+ ],
+ "billiards_dwd.dim_member_card_account": [("member_card_id", "id", None)],
+ "billiards_dwd.dim_member_card_account_ex": [
+ ("member_card_id", "id", None),
+ ("tenant_name", "tenantname", None),
+ ("tenantavatar", "tenantavatar", None),
+ ("card_no", "card_no", None),
+ ("bind_password", "bind_password", None),
+ ("use_scene", "use_scene", None),
+ ("tableareaid", "tableareaid", None),
+ ("goodscategoryid", "goodscategoryid", None),
+ ],
+ "billiards_dwd.dim_tenant_goods": [
+ ("tenant_goods_id", "id", None),
+ ("category_name", "categoryname", None),
+ ],
+ "billiards_dwd.dim_tenant_goods_ex": [
+ ("tenant_goods_id", "id", None),
+ ("remark_name", "remark_name", None),
+ ("goods_bar_code", "goods_bar_code", None),
+ ("commodity_code_list", "commodity_code", None),
+ ("is_in_site", "isinsite", "boolean"),
+ ],
+ "billiards_dwd.dim_store_goods": [
+ ("site_goods_id", "id", None),
+ ("category_level1_name", "onecategoryname", None),
+ ("category_level2_name", "twocategoryname", None),
+ ("created_at", "create_time", None),
+ ("updated_at", "update_time", None),
+ ("avg_monthly_sales", "average_monthly_sales", None),
+ ("batch_stock_qty", "stock", None),
+ ("sale_qty", "sale_num", None),
+ ("total_sales_qty", "total_sales", None),
+ ],
+ "billiards_dwd.dim_store_goods_ex": [
+ ("site_goods_id", "id", None),
+ ("goods_barcode", "goods_bar_code", None),
+ ("stock_qty", "stock", None),
+ ("stock_secondary_qty", "stock_a", None),
+ ("safety_stock_qty", "safe_stock", None),
+ ("site_name", "sitename", None),
+ ("goods_cover_url", "goods_cover", None),
+ ("provisional_total_cost", "total_purchase_cost", None),
+ ("is_discountable", "able_discount", None),
+ ("freeze_status", "freeze", None),
+ ("remark", "remark", None),
+ ("days_on_shelf", "days_available", None),
+ ("sort_order", "sort", None),
+ ],
+ "billiards_dwd.dim_goods_category": [
+ ("category_id", "id", None),
+ ("tenant_id", "tenant_id", None),
+ ("category_name", "category_name", None),
+ ("alias_name", "alias_name", None),
+ ("parent_category_id", "pid", None),
+ ("business_name", "business_name", None),
+ ("tenant_goods_business_id", "tenant_goods_business_id", None),
+ ("sort_order", "sort", None),
+ ("open_salesman", "open_salesman", None),
+ ("is_warehousing", "is_warehousing", None),
+ ("category_level", "CASE WHEN pid = 0 THEN 1 ELSE 2 END", None),
+ ("is_leaf", "CASE WHEN categoryboxes IS NULL OR jsonb_array_length(categoryboxes)=0 THEN 1 ELSE 0 END", None),
+ ],
+ "billiards_dwd.dim_groupbuy_package": [
+ ("groupbuy_package_id", "id", None),
+ ("package_template_id", "package_id", None),
+ ("coupon_face_value", "coupon_money", None),
+ ("duration_seconds", "duration", None),
+ ],
+ "billiards_dwd.dim_groupbuy_package_ex": [
+ ("groupbuy_package_id", "id", None),
+ ("table_area_id", "table_area_id", None),
+ ("tenant_table_area_id", "tenant_table_area_id", None),
+ ("usable_range", "usable_range", None),
+ ("table_area_id_list", "table_area_id_list", None),
+ ("package_type", "type", None),
+ ],
+ # 事实表主键及关键差异列
+ "billiards_dwd.dwd_table_fee_log": [("table_fee_log_id", "id", None)],
+ "billiards_dwd.dwd_table_fee_log_ex": [
+ ("table_fee_log_id", "id", None),
+ ("salesman_name", "salesman_name", None),
+ ],
+ "billiards_dwd.dwd_table_fee_adjust": [
+ ("table_fee_adjust_id", "id", None),
+ ("table_id", "site_table_id", None),
+ ("table_area_id", "tenant_table_area_id", None),
+ ("table_area_name", "tableprofile->>'table_area_name'", None),
+ ("adjust_time", "create_time", None),
+ ],
+ "billiards_dwd.dwd_table_fee_adjust_ex": [
+ ("table_fee_adjust_id", "id", None),
+ ("ledger_name", "ledger_name", None),
+ ],
+ "billiards_dwd.dwd_store_goods_sale": [("store_goods_sale_id", "id", None), ("discount_price", "discount_money", None)],
+ "billiards_dwd.dwd_store_goods_sale_ex": [
+ ("store_goods_sale_id", "id", None),
+ ("option_value_name", "option_value_name", None),
+ ("open_salesman_flag", "opensalesman", "integer"),
+ ("salesman_name", "salesman_name", None),
+ ("salesman_org_id", "sales_man_org_id", None),
+ ("legacy_order_goods_id", "ordergoodsid", None),
+ ("site_name", "sitename", None),
+ ("legacy_site_id", "siteid", None),
+ ],
+ "billiards_dwd.dwd_assistant_service_log": [
+ ("assistant_service_id", "id", None),
+ ("assistant_no", "assistantno", None),
+ ("site_assistant_id", "order_assistant_id", None),
+ ("level_name", "levelname", None),
+ ("skill_name", "skillname", None),
+ ],
+ "billiards_dwd.dwd_assistant_service_log_ex": [
+ ("assistant_service_id", "id", None),
+ ("assistant_name", "assistantname", None),
+ ("ledger_group_name", "ledger_group_name", None),
+ ("trash_applicant_name", "trash_applicant_name", None),
+ ("trash_reason", "trash_reason", None),
+ ("salesman_name", "salesman_name", None),
+ ("table_name", "tablename", None),
+ ],
+ "billiards_dwd.dwd_assistant_trash_event": [
+ ("assistant_trash_event_id", "id", None),
+ ("assistant_no", "assistantname", None),
+ ("abolish_amount", "assistantabolishamount", None),
+ ("charge_minutes_raw", "pdchargeminutes", None),
+ ("site_id", "siteid", None),
+ ("table_id", "tableid", None),
+ ("table_area_id", "tableareaid", None),
+ ("assistant_name", "assistantname", None),
+ ("trash_reason", "trashreason", None),
+ ("create_time", "createtime", None),
+ ],
+ "billiards_dwd.dwd_assistant_trash_event_ex": [
+ ("assistant_trash_event_id", "id", None),
+ ("table_area_name", "tablearea", None),
+ ("table_name", "tablename", None),
+ ],
+ "billiards_dwd.dwd_member_balance_change": [
+ ("balance_change_id", "id", None),
+ ("balance_before", "before", None),
+ ("change_amount", "account_data", None),
+ ("balance_after", "after", None),
+ ("card_type_name", "membercardtypename", None),
+ ("change_time", "create_time", None),
+ ("member_name", "membername", None),
+ ("member_mobile", "membermobile", None),
+ ],
+ "billiards_dwd.dwd_member_balance_change_ex": [
+ ("balance_change_id", "id", None),
+ ("pay_site_name", "paysitename", None),
+ ("register_site_name", "registersitename", None),
+ ],
+ "billiards_dwd.dwd_groupbuy_redemption": [("redemption_id", "id", None)],
+ "billiards_dwd.dwd_groupbuy_redemption_ex": [
+ ("redemption_id", "id", None),
+ ("table_area_name", "tableareaname", None),
+ ("site_name", "sitename", None),
+ ("table_name", "tablename", None),
+ ("goods_option_price", "goodsoptionprice", None),
+ ("salesman_name", "salesman_name", None),
+ ("salesman_org_id", "sales_man_org_id", None),
+ ("ledger_group_name", "ledger_group_name", None),
+ ],
+ "billiards_dwd.dwd_platform_coupon_redemption": [("platform_coupon_redemption_id", "id", None)],
+ "billiards_dwd.dwd_platform_coupon_redemption_ex": [
+ ("platform_coupon_redemption_id", "id", None),
+ ("coupon_cover", "coupon_cover", None),
+ ],
+ "billiards_dwd.dwd_payment": [("payment_id", "id", None), ("pay_date", "pay_time", "date")],
+ "billiards_dwd.dwd_refund": [("refund_id", "id", None)],
+ "billiards_dwd.dwd_refund_ex": [
+ ("refund_id", "id", None),
+ ("tenant_name", "tenantname", None),
+ ("channel_payer_id", "channel_payer_id", None),
+ ("channel_pay_no", "channel_pay_no", None),
+ ],
+ # 结算头:settlement_records(源列为小写驼峰/无下划线,需要显式映射)
+ "billiards_dwd.dwd_settlement_head": [
+ ("order_settle_id", "id", None),
+ ("tenant_id", "tenantid", None),
+ ("site_id", "siteid", None),
+ ("site_name", "sitename", None),
+ ("table_id", "tableid", None),
+ ("settle_name", "settlename", None),
+ ("order_trade_no", "settlerelateid", None),
+ ("create_time", "createtime", None),
+ ("pay_time", "paytime", None),
+ ("settle_type", "settletype", None),
+ ("revoke_order_id", "revokeorderid", None),
+ ("member_id", "memberid", None),
+ ("member_name", "membername", None),
+ ("member_phone", "memberphone", None),
+ ("member_card_account_id", "tenantmembercardid", None),
+ ("member_card_type_name", "membercardtypename", None),
+ ("is_bind_member", "isbindmember", None),
+ ("member_discount_amount", "memberdiscountamount", None),
+ ("consume_money", "consumemoney", None),
+ ("table_charge_money", "tablechargemoney", None),
+ ("goods_money", "goodsmoney", None),
+ ("real_goods_money", "realgoodsmoney", None),
+ ("assistant_pd_money", "assistantpdmoney", None),
+ ("assistant_cx_money", "assistantcxmoney", None),
+ ("adjust_amount", "adjustamount", None),
+ ("pay_amount", "payamount", None),
+ ("balance_amount", "balanceamount", None),
+ ("recharge_card_amount", "rechargecardamount", None),
+ ("gift_card_amount", "giftcardamount", None),
+ ("coupon_amount", "couponamount", None),
+ ("rounding_amount", "roundingamount", None),
+ ("point_amount", "pointamount", None),
+ ],
+ "billiards_dwd.dwd_settlement_head_ex": [
+ ("order_settle_id", "id", None),
+ ("serial_number", "serialnumber", None),
+ ("settle_status", "settlestatus", None),
+ ("can_be_revoked", "canberevoked", "boolean"),
+ ("revoke_order_name", "revokeordername", None),
+ ("revoke_time", "revoketime", None),
+ ("is_first_order", "isfirst", "boolean"),
+ ("service_money", "servicemoney", None),
+ ("cash_amount", "cashamount", None),
+ ("card_amount", "cardamount", None),
+ ("online_amount", "onlineamount", None),
+ ("refund_amount", "refundamount", None),
+ ("prepay_money", "prepaymoney", None),
+ ("payment_method", "paymentmethod", None),
+ ("coupon_sale_amount", "couponsaleamount", None),
+ ("all_coupon_discount", "allcoupondiscount", None),
+ ("goods_promotion_money", "goodspromotionmoney", None),
+ ("assistant_promotion_money", "assistantpromotionmoney", None),
+ ("activity_discount", "activitydiscount", None),
+ ("assistant_manual_discount", "assistantmanualdiscount", None),
+ ("point_discount_price", "pointdiscountprice", None),
+ ("point_discount_cost", "pointdiscountcost", None),
+ ("is_use_coupon", "isusecoupon", "boolean"),
+ ("is_use_discount", "isusediscount", "boolean"),
+ ("is_activity", "isactivity", "boolean"),
+ ("operator_name", "operatorname", None),
+ ("salesman_name", "salesmanname", None),
+ ("order_remark", "orderremark", None),
+ ("operator_id", "operatorid", None),
+ ("salesman_user_id", "salesmanuserid", None),
+ ],
+ # 充值结算:recharge_settlements(字段风格同 settlement_records)
+ "billiards_dwd.dwd_recharge_order": [
+ ("recharge_order_id", "id", None),
+ ("tenant_id", "tenantid", None),
+ ("site_id", "siteid", None),
+ ("member_id", "memberid", None),
+ ("member_name_snapshot", "membername", None),
+ ("member_phone_snapshot", "memberphone", None),
+ ("tenant_member_card_id", "tenantmembercardid", None),
+ ("member_card_type_name", "membercardtypename", None),
+ ("settle_relate_id", "settlerelateid", None),
+ ("settle_type", "settletype", None),
+ ("settle_name", "settlename", None),
+ ("is_first", "isfirst", None),
+ ("pay_amount", "payamount", None),
+ ("refund_amount", "refundamount", None),
+ ("point_amount", "pointamount", None),
+ ("cash_amount", "cashamount", None),
+ ("payment_method", "paymentmethod", None),
+ ("create_time", "createtime", None),
+ ("pay_time", "paytime", None),
+ ],
+ "billiards_dwd.dwd_recharge_order_ex": [
+ ("recharge_order_id", "id", None),
+ ("site_name_snapshot", "sitename", None),
+ ("salesman_name", "salesmanname", None),
+ ("order_remark", "orderremark", None),
+ ("revoke_order_name", "revokeordername", None),
+ ("settle_status", "settlestatus", None),
+ ("is_bind_member", "isbindmember", "boolean"),
+ ("is_activity", "isactivity", "boolean"),
+ ("is_use_coupon", "isusecoupon", "boolean"),
+ ("is_use_discount", "isusediscount", "boolean"),
+ ("can_be_revoked", "canberevoked", "boolean"),
+ ("online_amount", "onlineamount", None),
+ ("balance_amount", "balanceamount", None),
+ ("card_amount", "cardamount", None),
+ ("coupon_amount", "couponamount", None),
+ ("recharge_card_amount", "rechargecardamount", None),
+ ("gift_card_amount", "giftcardamount", None),
+ ("prepay_money", "prepaymoney", None),
+ ("consume_money", "consumemoney", None),
+ ("goods_money", "goodsmoney", None),
+ ("real_goods_money", "realgoodsmoney", None),
+ ("table_charge_money", "tablechargemoney", None),
+ ("service_money", "servicemoney", None),
+ ("activity_discount", "activitydiscount", None),
+ ("all_coupon_discount", "allcoupondiscount", None),
+ ("goods_promotion_money", "goodspromotionmoney", None),
+ ("assistant_promotion_money", "assistantpromotionmoney", None),
+ ("assistant_pd_money", "assistantpdmoney", None),
+ ("assistant_cx_money", "assistantcxmoney", None),
+ ("assistant_manual_discount", "assistantmanualdiscount", None),
+ ("coupon_sale_amount", "couponsaleamount", None),
+ ("member_discount_amount", "memberdiscountamount", None),
+ ("point_discount_price", "pointdiscountprice", None),
+ ("point_discount_cost", "pointdiscountcost", None),
+ ("adjust_amount", "adjustamount", None),
+ ("rounding_amount", "roundingamount", None),
+ ("operator_id", "operatorid", None),
+ ("operator_name_snapshot", "operatorname", None),
+ ("salesman_user_id", "salesmanuserid", None),
+ ("salesman_name", "salesmanname", None),
+ ("order_remark", "orderremark", None),
+ ("table_id", "tableid", None),
+ ("serial_number", "serialnumber", None),
+ ("revoke_order_id", "revokeorderid", None),
+ ("revoke_order_name", "revokeordername", None),
+ ("revoke_time", "revoketime", None),
+ ],
+ }
+
+ def get_task_code(self) -> str:
+ """返回任务编码。"""
+ return "DWD_LOAD_FROM_ODS"
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ """准备运行所需的上下文信息。"""
+ return {"now": datetime.now()}
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict[str, Any]:
+ """
+ 遍历映射关系,维度执行 SCD2 合并,事实表按时间增量插入。
+
+ 说明:
+ - 为避免长事务导致锁堆积/中断后遗留 idle-in-tx,本任务按“每张表一次事务”提交;
+ - 单表失败会回滚该表并继续后续表,最终在结果中汇总错误信息。
+ """
+ now = extracted["now"]
+ summary: List[Dict[str, Any]] = []
+ errors: List[Dict[str, Any]] = []
+ only_tables_cfg = self.config.get("dwd.only_tables") or []
+ only_tables = {str(t).strip().lower() for t in only_tables_cfg if str(t).strip()} if only_tables_cfg else set()
+ with self.db.conn.cursor(cursor_factory=RealDictCursor) as cur:
+ for dwd_table, ods_table in self.TABLE_MAP.items():
+ if only_tables and dwd_table.lower() not in only_tables and self._table_base(dwd_table).lower() not in only_tables:
+ continue
+ started = time.monotonic()
+ self.logger.info("DWD 装载开始:%s <= %s", dwd_table, ods_table)
+ try:
+ dwd_cols = self._get_columns(cur, dwd_table)
+ ods_cols = self._get_columns(cur, ods_table)
+ if not dwd_cols:
+ self.logger.warning("跳过 %s:未能获取 DWD 列信息", dwd_table)
+ continue
+
+ if self._table_base(dwd_table).startswith("dim_"):
+ processed = self._merge_dim(cur, dwd_table, ods_table, dwd_cols, ods_cols, now)
+ self.db.conn.commit()
+ summary.append({"table": dwd_table, "mode": "SCD2", "processed": processed})
+ else:
+ dwd_types = self._get_column_types(cur, dwd_table, "billiards_dwd")
+ ods_types = self._get_column_types(cur, ods_table, "billiards_ods")
+ use_window = bool(
+ self.config.get("run.window_override.start")
+ and self.config.get("run.window_override.end")
+ )
+ inserted = self._merge_fact_increment(
+ cur,
+ dwd_table,
+ ods_table,
+ dwd_cols,
+ ods_cols,
+ dwd_types,
+ ods_types,
+ window_start=context.window_start if use_window else None,
+ window_end=context.window_end if use_window else None,
+ )
+ self.db.conn.commit()
+ summary.append({"table": dwd_table, "mode": "INCREMENT", "inserted": inserted})
+
+ elapsed = time.monotonic() - started
+ self.logger.info("DWD 装载完成:%s,用时 %.2fs", dwd_table, elapsed)
+ except Exception as exc: # noqa: BLE001
+ try:
+ self.db.conn.rollback()
+ except Exception:
+ pass
+ elapsed = time.monotonic() - started
+ self.logger.exception("DWD 装载失败:%s,用时 %.2fs,err=%s", dwd_table, elapsed, exc)
+ errors.append({"table": dwd_table, "error": str(exc)})
+ continue
+
+ return {"tables": summary, "errors": errors}
+
+ # ---------------------- helpers ----------------------
+ def _get_columns(self, cur, table: str) -> List[str]:
+ """获取指定表的列名(小写)。"""
+ schema, name = self._split_table_name(table, default_schema="billiards_dwd")
+ cur.execute(
+ """
+ SELECT column_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ """,
+ (schema, name),
+ )
+ return [r["column_name"].lower() for r in cur.fetchall()]
+
+ def _get_primary_keys(self, cur, table: str) -> List[str]:
+ """获取表的主键列名列表。"""
+ schema, name = self._split_table_name(table, default_schema="billiards_dwd")
+ cur.execute(
+ """
+ SELECT kcu.column_name
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.constraint_name = kcu.constraint_name
+ AND tc.table_schema = kcu.table_schema
+ AND tc.table_name = kcu.table_name
+ WHERE tc.table_schema = %s
+ AND tc.table_name = %s
+ AND tc.constraint_type = 'PRIMARY KEY'
+ ORDER BY kcu.ordinal_position
+ """,
+ (schema, name),
+ )
+ return [r["column_name"].lower() for r in cur.fetchall()]
+
+ def _get_column_types(self, cur, table: str, default_schema: str) -> Dict[str, str]:
+ """获取列的数据类型(information_schema.data_type)。"""
+ schema, name = self._split_table_name(table, default_schema=default_schema)
+ cur.execute(
+ """
+ SELECT column_name, data_type
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ """,
+ (schema, name),
+ )
+ return {r["column_name"].lower(): r["data_type"].lower() for r in cur.fetchall()}
+
+ def _build_column_mapping(
+ self, dwd_table: str, pk_cols: Sequence[str], ods_cols: Sequence[str]
+ ) -> Dict[str, tuple[str, str | None]]:
+ """合并显式 FACT_MAPPINGS 与主键兜底映射。"""
+ mapping_entries = self.FACT_MAPPINGS.get(dwd_table, [])
+ mapping: Dict[str, tuple[str, str | None]] = {
+ dst.lower(): (src, cast_type) for dst, src, cast_type in mapping_entries
+ }
+ ods_set = {c.lower() for c in ods_cols}
+ for pk in pk_cols:
+ pk_lower = pk.lower()
+ if pk_lower not in mapping and pk_lower not in ods_set and "id" in ods_set:
+ mapping[pk_lower] = ("id", None)
+ return mapping
+
+ def _fetch_source_rows(
+ self, cur, table: str, columns: Sequence[str], where_sql: str = "", params: Sequence[Any] = None
+ ) -> List[Dict[str, Any]]:
+ """从源表读取指定列,返回小写键的字典列表。"""
+ schema, name = self._split_table_name(table, default_schema="billiards_ods")
+ cols_sql = ", ".join(f'"{c}"' for c in columns)
+ sql = f'SELECT {cols_sql} FROM "{schema}"."{name}" {where_sql}'
+ cur.execute(sql, params or [])
+ rows = []
+ for r in cur.fetchall():
+ rows.append({k.lower(): v for k, v in r.items()})
+ return rows
+
+ def _expand_goods_category_rows(self, rows: list[Dict[str, Any]]) -> list[Dict[str, Any]]:
+ """将分类表中的 categoryboxes 元素展开为子类记录。"""
+ expanded: list[Dict[str, Any]] = []
+ for r in rows:
+ expanded.append(r)
+ boxes = r.get("categoryboxes")
+ if isinstance(boxes, list):
+ for child in boxes:
+ if not isinstance(child, dict):
+ continue
+ child_row: Dict[str, Any] = {}
+ # 继承父级的租户与业务大类信息
+ child_row["tenant_id"] = r.get("tenant_id")
+ child_row["business_name"] = child.get("business_name", r.get("business_name"))
+ child_row["tenant_goods_business_id"] = child.get(
+ "tenant_goods_business_id", r.get("tenant_goods_business_id")
+ )
+ # 合并子类字段
+ child_row.update(child)
+ # 默认父子关系
+ child_row.setdefault("pid", r.get("id"))
+ # 衍生层级/叶子标记
+ child_boxes = child_row.get("categoryboxes")
+ if not isinstance(child_boxes, list):
+ is_leaf = 1
+ else:
+ is_leaf = 1 if len(child_boxes) == 0 else 0
+ child_row.setdefault("category_level", 2)
+ child_row.setdefault("is_leaf", is_leaf)
+ expanded.append(child_row)
+ return expanded
+
+ def _merge_dim(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ dwd_cols: Sequence[str],
+ ods_cols: Sequence[str],
+ now: datetime,
+ ) -> int:
+ """
+ 维表合并策略:
+ - 若主键包含 scd2 列(如 scd2_start_time/scd2_version),执行真正的 SCD2(关闭旧版+插入新版)。
+ - 否则(多数现有表主键仅为业务主键),执行 Type1 Upsert,避免重复键异常并保证可重复回放。
+ """
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ if not pk_cols:
+ raise ValueError(f"{dwd_table} 未配置主键,无法执行维表合并")
+
+ pk_has_scd = any(pk.lower() in self.SCD_COLS for pk in pk_cols)
+ scd_cols_present = any(c.lower() in self.SCD_COLS for c in dwd_cols)
+ if scd_cols_present and pk_has_scd:
+ return self._merge_dim_scd2(cur, dwd_table, ods_table, dwd_cols, ods_cols, now)
+ return self._merge_dim_type1_upsert(cur, dwd_table, ods_table, dwd_cols, ods_cols, pk_cols, now)
+
+ def _merge_dim_type1_upsert(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ dwd_cols: Sequence[str],
+ ods_cols: Sequence[str],
+ pk_cols: Sequence[str],
+ now: datetime,
+ ) -> int:
+ """维表 Type1 Upsert(主键冲突则更新),兼容带 scd2 字段但主键不支持多版本的表。"""
+ mapping = self._build_column_mapping(dwd_table, pk_cols, ods_cols)
+ ods_set = {c.lower() for c in ods_cols}
+ ods_table_sql = self._format_table(ods_table, "billiards_ods")
+
+ select_exprs: list[str] = []
+ added: set[str] = set()
+ for col in dwd_cols:
+ lc = col.lower()
+ if lc in self.SCD_COLS:
+ continue
+ if lc in mapping:
+ src, cast_type = mapping[lc]
+ select_exprs.append(f"{self._cast_expr(src, cast_type)} AS \"{lc}\"")
+ added.add(lc)
+ elif lc in ods_set:
+ select_exprs.append(f'\"{lc}\" AS \"{lc}\"')
+ added.add(lc)
+
+ for pk in pk_cols:
+ lc = pk.lower()
+ if lc in added:
+ continue
+ if lc in mapping:
+ src, cast_type = mapping[lc]
+ select_exprs.append(f"{self._cast_expr(src, cast_type)} AS \"{lc}\"")
+ elif lc in ods_set:
+ select_exprs.append(f'\"{lc}\" AS \"{lc}\"')
+ added.add(lc)
+
+ if not select_exprs:
+ return 0
+
+ # 对于 dim_site 和 dim_site_ex,使用 DISTINCT ON 优化查询
+ # 避免从大表 table_fee_transactions 全表扫描,只获取每个 site_id 的最新记录
+ if dwd_table in ("billiards_dwd.dim_site", "billiards_dwd.dim_site_ex"):
+ sql = f"SELECT DISTINCT ON (site_id) {', '.join(select_exprs)} FROM {ods_table_sql} ORDER BY site_id, fetched_at DESC NULLS LAST"
+ else:
+ sql = f"SELECT {', '.join(select_exprs)} FROM {ods_table_sql}"
+
+ cur.execute(sql)
+ rows = [{k.lower(): v for k, v in r.items()} for r in cur.fetchall()]
+
+ if dwd_table == "billiards_dwd.dim_goods_category":
+ rows = self._expand_goods_category_rows(rows)
+
+ # 按主键去重
+ seen_pk: set[tuple[Any, ...]] = set()
+ src_rows: list[Dict[str, Any]] = []
+ pk_lower = [c.lower() for c in pk_cols]
+ for row in rows:
+ pk_key = tuple(row.get(pk) for pk in pk_lower)
+ if pk_key in seen_pk:
+ continue
+ if any(v is None for v in pk_key):
+ self.logger.warning("跳过 %s:主键缺失 %s", dwd_table, dict(zip(pk_cols, pk_key)))
+ continue
+ seen_pk.add(pk_key)
+ src_rows.append(row)
+
+ if not src_rows:
+ return 0
+
+ dwd_table_sql = self._format_table(dwd_table, "billiards_dwd")
+ sorted_cols = [c.lower() for c in sorted(dwd_cols)]
+ insert_cols_sql = ", ".join(f'\"{c}\"' for c in sorted_cols)
+
+ def build_row(src_row: Dict[str, Any]) -> list[Any]:
+ values: list[Any] = []
+ for c in sorted_cols:
+ if c == "scd2_start_time":
+ values.append(now)
+ elif c == "scd2_end_time":
+ values.append(datetime(9999, 12, 31, 0, 0, 0))
+ elif c == "scd2_is_current":
+ values.append(1)
+ elif c == "scd2_version":
+ values.append(1)
+ else:
+ values.append(src_row.get(c))
+ return values
+
+ pk_sql = ", ".join(f'\"{c.lower()}\"' for c in pk_cols)
+ pk_lower_set = {c.lower() for c in pk_cols}
+ set_exprs: list[str] = []
+ for c in sorted_cols:
+ if c in pk_lower_set:
+ continue
+ if c == "scd2_start_time":
+ set_exprs.append(f'\"{c}\" = COALESCE({dwd_table_sql}.\"{c}\", EXCLUDED.\"{c}\")')
+ elif c == "scd2_version":
+ set_exprs.append(f'\"{c}\" = COALESCE({dwd_table_sql}.\"{c}\", EXCLUDED.\"{c}\")')
+ else:
+ set_exprs.append(f'\"{c}\" = EXCLUDED.\"{c}\"')
+
+ upsert_sql = (
+ f"INSERT INTO {dwd_table_sql} ({insert_cols_sql}) VALUES %s "
+ f"ON CONFLICT ({pk_sql}) DO UPDATE SET {', '.join(set_exprs)}"
+ )
+ execute_values(cur, upsert_sql, [build_row(r) for r in src_rows], page_size=500)
+ return len(src_rows)
+
+ def _merge_dim_scd2(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ dwd_cols: Sequence[str],
+ ods_cols: Sequence[str],
+ now: datetime,
+ ) -> int:
+ """对维表执行 SCD2 合并:对比变更关闭旧版并插入新版。"""
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ if not pk_cols:
+ raise ValueError(f"{dwd_table} 未配置主键,无法执行 SCD2 合并")
+
+ mapping = self._build_column_mapping(dwd_table, pk_cols, ods_cols)
+ ods_set = {c.lower() for c in ods_cols}
+ table_sql = self._format_table(ods_table, "billiards_ods")
+ # 构造 SELECT 表达式,支持 JSON/expression 映射
+ select_exprs: list[str] = []
+ added: set[str] = set()
+ for col in dwd_cols:
+ lc = col.lower()
+ if lc in self.SCD_COLS:
+ continue
+ if lc in mapping:
+ src, cast_type = mapping[lc]
+ select_exprs.append(f"{self._cast_expr(src, cast_type)} AS \"{lc}\"")
+ added.add(lc)
+ elif lc in ods_set:
+ select_exprs.append(f'"{lc}" AS "{lc}"')
+ added.add(lc)
+ # 分类维度需要额外读取 categoryboxes 以展开子类
+ if dwd_table == "billiards_dwd.dim_goods_category" and "categoryboxes" not in added and "categoryboxes" in ods_set:
+ select_exprs.append('"categoryboxes" AS "categoryboxes"')
+ added.add("categoryboxes")
+ # 主键兜底确保被选出
+ for pk in pk_cols:
+ lc = pk.lower()
+ if lc not in added:
+ if lc in mapping:
+ src, cast_type = mapping[lc]
+ select_exprs.append(f"{self._cast_expr(src, cast_type)} AS \"{lc}\"")
+ elif lc in ods_set:
+ select_exprs.append(f'"{lc}" AS "{lc}"')
+ added.add(lc)
+
+ if not select_exprs:
+ return 0
+
+ sql = f"SELECT {', '.join(select_exprs)} FROM {table_sql}"
+ cur.execute(sql)
+ rows = [{k.lower(): v for k, v in r.items()} for r in cur.fetchall()]
+
+ # 特殊:分类维度展开子类
+ if dwd_table == "billiards_dwd.dim_goods_category":
+ rows = self._expand_goods_category_rows(rows)
+
+ # 归一化源行并按主键去重
+ seen_pk = set()
+ src_rows_by_pk: dict[tuple[Any, ...], Dict[str, Any]] = {}
+ for row in rows:
+ mapped_row: Dict[str, Any] = {}
+ for col in dwd_cols:
+ lc = col.lower()
+ if lc in self.SCD_COLS:
+ continue
+ value = row.get(lc)
+ if value is None and lc in mapping:
+ src, _ = mapping[lc]
+ value = row.get(src.lower())
+ mapped_row[lc] = value
+
+ pk_key = tuple(mapped_row.get(pk) for pk in pk_cols)
+ if pk_key in seen_pk:
+ continue
+ if any(v is None for v in pk_key):
+ self.logger.warning("跳过 %s:主键缺失 %s", dwd_table, dict(zip(pk_cols, pk_key)))
+ continue
+ seen_pk.add(pk_key)
+ src_rows_by_pk[pk_key] = mapped_row
+
+ if not src_rows_by_pk:
+ return 0
+
+ # 预加载当前版本(scd2_is_current=1),避免逐行 SELECT 造成大量 round-trip
+ table_sql_dwd = self._format_table(dwd_table, "billiards_dwd")
+ where_current = " AND ".join([f"COALESCE(scd2_is_current,1)=1"])
+ cur.execute(f"SELECT * FROM {table_sql_dwd} WHERE {where_current}")
+ current_rows = cur.fetchall() or []
+ current_by_pk: dict[tuple[Any, ...], Dict[str, Any]] = {}
+ for r in current_rows:
+ rr = {k.lower(): v for k, v in r.items()}
+ pk_key = tuple(rr.get(pk) for pk in pk_cols)
+ current_by_pk[pk_key] = rr
+
+ # 计算需要关闭/插入的主键集合
+ to_close: list[tuple[Any, ...]] = []
+ to_insert: list[tuple[Dict[str, Any], int]] = []
+ for pk_key, incoming in src_rows_by_pk.items():
+ current = current_by_pk.get(pk_key)
+ if current and not self._is_row_changed(current, incoming, dwd_cols):
+ continue
+ if current:
+ version = (current.get("scd2_version") or 1) + 1
+ to_close.append(pk_key)
+ else:
+ version = 1
+ to_insert.append((incoming, version))
+
+ # 先关闭旧版本(同一批次统一 end_time)
+ if to_close:
+ self._close_current_dim_bulk(cur, dwd_table, pk_cols, to_close, now)
+
+ # 批量插入新版本
+ if to_insert:
+ self._insert_dim_rows_bulk(cur, dwd_table, dwd_cols, to_insert, now)
+
+ return len(src_rows_by_pk)
+
+ def _close_current_dim_bulk(
+ self,
+ cur,
+ table: str,
+ pk_cols: Sequence[str],
+ pk_keys: Sequence[tuple[Any, ...]],
+ now: datetime,
+ ) -> None:
+ """批量关闭当前版本(scd2_is_current=0 + 填充结束时间)。"""
+ table_sql = self._format_table(table, "billiards_dwd")
+ if len(pk_cols) == 1:
+ pk = pk_cols[0]
+ ids = [k[0] for k in pk_keys]
+ cur.execute(
+ f'UPDATE {table_sql} SET scd2_end_time=%s, scd2_is_current=0 '
+ f'WHERE COALESCE(scd2_is_current,1)=1 AND "{pk}" = ANY(%s)',
+ (now, ids),
+ )
+ return
+
+ # 复合主键:对“发生变更的键”逐条关闭(数量通常远小于全量行数)
+ where_clause = " AND ".join(f'"{pk}" = %s' for pk in pk_cols)
+ sql = (
+ f"UPDATE {table_sql} SET scd2_end_time=%s, scd2_is_current=0 "
+ f"WHERE COALESCE(scd2_is_current,1)=1 AND {where_clause}"
+ )
+ args_list = [(now, *pk_key) for pk_key in pk_keys]
+ execute_batch(cur, sql, args_list, page_size=500)
+
+ def _insert_dim_rows_bulk(
+ self,
+ cur,
+ table: str,
+ dwd_cols: Sequence[str],
+ rows_with_version: Sequence[tuple[Dict[str, Any], int]],
+ now: datetime,
+ ) -> None:
+ """批量插入新的 SCD2 版本行。"""
+ sorted_cols = [c.lower() for c in sorted(dwd_cols)]
+ insert_cols_sql = ", ".join(f'"{c}"' for c in sorted_cols)
+ table_sql = self._format_table(table, "billiards_dwd")
+
+ def build_row(src_row: Dict[str, Any], version: int) -> list[Any]:
+ values: list[Any] = []
+ for c in sorted_cols:
+ if c == "scd2_start_time":
+ values.append(now)
+ elif c == "scd2_end_time":
+ values.append(datetime(9999, 12, 31, 0, 0, 0))
+ elif c == "scd2_is_current":
+ values.append(1)
+ elif c == "scd2_version":
+ values.append(version)
+ else:
+ values.append(src_row.get(c))
+ return values
+
+ values_rows = [build_row(r, ver) for r, ver in rows_with_version]
+ insert_sql = f"INSERT INTO {table_sql} ({insert_cols_sql}) VALUES %s"
+ execute_values(cur, insert_sql, values_rows, page_size=500)
+
+ def _upsert_scd2_row(
+ self,
+ cur,
+ dwd_table: str,
+ dwd_cols: Sequence[str],
+ pk_cols: Sequence[str],
+ src_row: Dict[str, Any],
+ now: datetime,
+ ) -> bool:
+ """SCD2 合并:若有变更则关闭旧版并插入新版本。"""
+ pk_values = [src_row.get(pk) for pk in pk_cols]
+ if any(v is None for v in pk_values):
+ self.logger.warning("跳过 %s:主键缺失 %s", dwd_table, dict(zip(pk_cols, pk_values)))
+ return False
+
+ where_clause = " AND ".join(f'"{pk}" = %s' for pk in pk_cols)
+ table_sql = self._format_table(dwd_table, "billiards_dwd")
+ cur.execute(
+ f"SELECT * FROM {table_sql} WHERE {where_clause} AND COALESCE(scd2_is_current,1)=1 LIMIT 1",
+ pk_values,
+ )
+ current = cur.fetchone()
+ if current:
+ current = {k.lower(): v for k, v in current.items()}
+
+ if current and not self._is_row_changed(current, src_row, dwd_cols):
+ return False
+
+ if current:
+ version = (current.get("scd2_version") or 1) + 1
+ self._close_current_dim(cur, dwd_table, pk_cols, pk_values, now)
+ else:
+ version = 1
+
+ self._insert_dim_row(cur, dwd_table, dwd_cols, src_row, now, version)
+ return True
+
+ def _close_current_dim(self, cur, table: str, pk_cols: Sequence[str], pk_values: Sequence[Any], now: datetime) -> None:
+ """关闭当前版本,标记 scd2_is_current=0 并填充结束时间。"""
+ set_sql = "scd2_end_time = %s, scd2_is_current = 0"
+ where_clause = " AND ".join(f'"{pk}" = %s' for pk in pk_cols)
+ table_sql = self._format_table(table, "billiards_dwd")
+ cur.execute(f"UPDATE {table_sql} SET {set_sql} WHERE {where_clause} AND COALESCE(scd2_is_current,1)=1", [now, *pk_values])
+
+ def _insert_dim_row(
+ self,
+ cur,
+ table: str,
+ dwd_cols: Sequence[str],
+ src_row: Dict[str, Any],
+ now: datetime,
+ version: int,
+ ) -> None:
+ """插入新的 SCD2 版本行。"""
+ insert_cols: List[str] = []
+ placeholders: List[str] = []
+ values: List[Any] = []
+ for col in sorted(dwd_cols):
+ lc = col.lower()
+ insert_cols.append(f'"{lc}"')
+ placeholders.append("%s")
+ if lc == "scd2_start_time":
+ values.append(now)
+ elif lc == "scd2_end_time":
+ values.append(datetime(9999, 12, 31, 0, 0, 0))
+ elif lc == "scd2_is_current":
+ values.append(1)
+ elif lc == "scd2_version":
+ values.append(version)
+ else:
+ values.append(src_row.get(lc))
+ table_sql = self._format_table(table, "billiards_dwd")
+ sql = f'INSERT INTO {table_sql} ({", ".join(insert_cols)}) VALUES ({", ".join(placeholders)})'
+ cur.execute(sql, values)
+
+ def _is_row_changed(self, current: Dict[str, Any], incoming: Dict[str, Any], dwd_cols: Sequence[str]) -> bool:
+ """比较非 SCD2 列,判断是否存在变更。"""
+ for col in dwd_cols:
+ lc = col.lower()
+ if lc in self.SCD_COLS:
+ continue
+ if current.get(lc) != incoming.get(lc):
+ return True
+ return False
+
+ def _merge_fact_increment(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ dwd_cols: Sequence[str],
+ ods_cols: Sequence[str],
+ dwd_types: Dict[str, str],
+ ods_types: Dict[str, str],
+ window_start: datetime | None = None,
+ window_end: datetime | None = None,
+ ) -> int:
+ """事实表按时间增量插入,默认按列名交集写入。"""
+ mapping_entries = self.FACT_MAPPINGS.get(dwd_table) or []
+ mapping: Dict[str, tuple[str, str | None]] = {
+ dst.lower(): (src, cast_type) for dst, src, cast_type in mapping_entries
+ }
+
+ mapping_dest = [dst for dst, _, _ in mapping_entries]
+ insert_cols: List[str] = list(mapping_dest)
+ for col in dwd_cols:
+ if col in self.SCD_COLS:
+ continue
+ if col in insert_cols:
+ continue
+ if col in ods_cols:
+ insert_cols.append(col)
+
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ ods_set = {c.lower() for c in ods_cols}
+ existing_lower = [c.lower() for c in insert_cols]
+ for pk in pk_cols:
+ pk_lower = pk.lower()
+ if pk_lower in existing_lower:
+ continue
+ if pk_lower in ods_set:
+ insert_cols.append(pk)
+ existing_lower.append(pk_lower)
+ elif "id" in ods_set:
+ insert_cols.append(pk)
+ existing_lower.append(pk_lower)
+ mapping[pk_lower] = ("id", None)
+
+ # 保持列顺序同时去重
+ seen_cols: set[str] = set()
+ ordered_cols: list[str] = []
+ for col in insert_cols:
+ lc = col.lower()
+ if lc not in seen_cols:
+ seen_cols.add(lc)
+ ordered_cols.append(col)
+ insert_cols = ordered_cols
+
+ if not insert_cols:
+ self.logger.warning("跳过 %s:未找到可插入的列", dwd_table)
+ return 0
+
+ order_col = self._pick_order_column(dwd_table, dwd_cols, ods_cols)
+ where_sql = ""
+ params: List[Any] = []
+ dwd_table_sql = self._format_table(dwd_table, "billiards_dwd")
+ ods_table_sql = self._format_table(ods_table, "billiards_ods")
+ if order_col and window_start and window_end:
+ where_sql = f'WHERE "{order_col}" >= %s AND "{order_col}" < %s'
+ params.extend([window_start, window_end])
+ elif order_col:
+ watermark = self._get_fact_watermark(cur, dwd_table, ods_table, order_col, dwd_cols, ods_cols)
+ where_sql = f'WHERE "{order_col}" > %s'
+ params.append(watermark)
+
+ default_cols = [c for c in insert_cols if c.lower() not in mapping]
+ default_expr_map: Dict[str, str] = {}
+ if default_cols:
+ default_exprs = self._build_fact_select_exprs(default_cols, dwd_types, ods_types)
+ default_expr_map = dict(zip(default_cols, default_exprs))
+
+ select_exprs: List[str] = []
+ for col in insert_cols:
+ key = col.lower()
+ if key in mapping:
+ src, cast_type = mapping[key]
+ select_exprs.append(self._cast_expr(src, cast_type))
+ else:
+ select_exprs.append(default_expr_map[col])
+
+ select_cols_sql = ", ".join(select_exprs)
+ insert_cols_sql = ", ".join(f'"{c}"' for c in insert_cols)
+ sql = f'INSERT INTO {dwd_table_sql} ({insert_cols_sql}) SELECT {select_cols_sql} FROM {ods_table_sql} {where_sql}'
+
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ if pk_cols:
+ pk_sql = ", ".join(f'"{c}"' for c in pk_cols)
+ sql += f" ON CONFLICT ({pk_sql}) DO NOTHING"
+
+ cur.execute(sql, params)
+ inserted = cur.rowcount
+
+ # 回补缺失主键记录(处理历史回补导致的“create_time 水位”遗漏)
+ if dwd_table.lower() in self.FACT_MISSING_FILL_TABLES:
+ inserted += self._insert_missing_by_pk(
+ cur,
+ dwd_table,
+ ods_table,
+ dwd_cols,
+ ods_cols,
+ mapping,
+ insert_cols,
+ dwd_types,
+ ods_types,
+ )
+
+ return inserted
+ def _pick_order_column(self, dwd_table: str, dwd_cols: Iterable[str], ods_cols: Iterable[str]) -> str | None:
+ """Pick an incremental order column that exists in both DWD and ODS."""
+ lower_cols = {c.lower() for c in dwd_cols} & {c.lower() for c in ods_cols}
+ for candidate in self.FACT_ORDER_CANDIDATES:
+ if candidate.lower() in lower_cols:
+ return candidate.lower()
+ return None
+
+ def _get_fact_watermark(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ order_col: str,
+ dwd_cols: Iterable[str],
+ ods_cols: Iterable[str],
+ ) -> Any:
+ """Fetch incremental watermark; default from DWD, fallback from ODS join."""
+ dwd_table_sql = self._format_table(dwd_table, "billiards_dwd")
+ ods_table_sql = self._format_table(ods_table, "billiards_ods")
+ dwd_set = {c.lower() for c in dwd_cols}
+ ods_set = {c.lower() for c in ods_cols}
+ if order_col.lower() in dwd_set:
+ cur.execute(
+ f'SELECT COALESCE(MAX("{order_col}"), %s) FROM {dwd_table_sql}', ("1970-01-01",)
+ )
+ row = cur.fetchone() or {}
+ return list(row.values())[0] if row else "1970-01-01"
+
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ if not pk_cols or order_col.lower() not in ods_set:
+ return "1970-01-01"
+
+ join_cond = " AND ".join(f'd."{pk}" = o."{pk}"' for pk in pk_cols if pk.lower() in ods_set)
+ if not join_cond:
+ return "1970-01-01"
+
+ cur.execute(
+ f'SELECT COALESCE(MAX(o."{order_col}"), %s) FROM {ods_table_sql} o JOIN {dwd_table_sql} d ON {join_cond}',
+ ("1970-01-01",),
+ )
+ row = cur.fetchone() or {}
+ return list(row.values())[0] if row else "1970-01-01"
+
+ def _insert_missing_by_pk(
+ self,
+ cur,
+ dwd_table: str,
+ ods_table: str,
+ dwd_cols: Sequence[str],
+ ods_cols: Sequence[str],
+ mapping: Dict[str, tuple[str, str | None]],
+ insert_cols: Sequence[str],
+ dwd_types: Dict[str, str],
+ ods_types: Dict[str, str],
+ ) -> int:
+ """Backfill missing PK rows for facts that can receive late data."""
+ pk_cols = self._get_primary_keys(cur, dwd_table)
+ if not pk_cols:
+ return 0
+
+ ods_set = {c.lower() for c in ods_cols}
+ dwd_table_sql = self._format_table(dwd_table, "billiards_dwd")
+ ods_table_sql = self._format_table(ods_table, "billiards_ods")
+
+ join_pairs = []
+ for pk in pk_cols:
+ pk_lower = pk.lower()
+ if pk_lower in mapping:
+ src, _ = mapping[pk_lower]
+ elif pk_lower in ods_set:
+ src = pk
+ elif "id" in ods_set:
+ src = "id"
+ else:
+ src = None
+ if not src:
+ return 0
+ join_pairs.append((pk, src))
+
+ join_cond = " AND ".join(
+ f'd."{pk}" = o."{src}"' for pk, src in join_pairs
+ )
+ null_cond = " AND ".join(f'd."{pk}" IS NULL' for pk, _ in join_pairs)
+
+ # 类型转换需要的类型集合
+ numeric_types = {"integer", "bigint", "smallint", "numeric", "double precision", "real", "decimal"}
+ text_types = {"text", "character varying", "varchar"}
+
+ select_exprs = []
+ for col in insert_cols:
+ key = col.lower()
+ if key in mapping:
+ src, cast_type = mapping[key]
+ if src.isidentifier():
+ expr = self._cast_expr(f'o."{src}"', cast_type)
+ else:
+ expr = self._cast_expr(src, cast_type)
+ select_exprs.append(expr)
+ elif key in ods_set:
+ # 检查是否需要类型转换 (ODS text -> DWD numeric)
+ d_type = dwd_types.get(col)
+ o_type = ods_types.get(col)
+ if d_type in numeric_types and o_type in text_types:
+ select_exprs.append(f'CAST(NULLIF(CAST(o."{col}" AS text), \'\') AS {d_type})')
+ else:
+ select_exprs.append(f'o."{col}"')
+ else:
+ select_exprs.append("NULL")
+
+ select_cols_sql = ", ".join(select_exprs)
+ insert_cols_sql = ", ".join(f'"{c}"' for c in insert_cols)
+ sql = (
+ f'INSERT INTO {dwd_table_sql} ({insert_cols_sql}) '
+ f'SELECT {select_cols_sql} '
+ f'FROM {ods_table_sql} o '
+ f'LEFT JOIN {dwd_table_sql} d ON {join_cond} '
+ f'WHERE {null_cond}'
+ )
+
+ pk_sql = ", ".join(f'"{c}"' for c in pk_cols)
+ sql += f" ON CONFLICT ({pk_sql}) DO NOTHING"
+
+ cur.execute(sql)
+ return cur.rowcount
+
+ def _build_fact_select_exprs(
+ self,
+ insert_cols: Sequence[str],
+ dwd_types: Dict[str, str],
+ ods_types: Dict[str, str],
+ ) -> List[str]:
+ """构造事实表 SELECT 列表,需要时做类型转换。"""
+ numeric_types = {"integer", "bigint", "smallint", "numeric", "double precision", "real", "decimal"}
+ text_types = {"text", "character varying", "varchar"}
+ exprs = []
+ for col in insert_cols:
+ d_type = dwd_types.get(col)
+ o_type = ods_types.get(col)
+ if d_type in numeric_types and o_type in text_types:
+ exprs.append(f"CAST(NULLIF(CAST(\"{col}\" AS text), '') AS numeric):: {d_type}")
+ else:
+ exprs.append(f'"{col}"')
+ return exprs
+
+ def _split_table_name(self, name: str, default_schema: str) -> tuple[str, str]:
+ """拆分 schema.table,若无 schema 则补默认 schema。"""
+ parts = name.split(".")
+ if len(parts) == 2:
+ return parts[0], parts[1].lower()
+ return default_schema, name.lower()
+
+ def _table_base(self, name: str) -> str:
+ """获取不含 schema 的表名。"""
+ return name.split(".")[-1]
+
+ def _format_table(self, name: str, default_schema: str) -> str:
+ """返回带引号的 schema.table 名称。"""
+ schema, table = self._split_table_name(name, default_schema)
+ return f'"{schema}"."{table}"'
+
+ def _cast_expr(self, col: str, cast_type: str | None) -> str:
+ """构造带可选 CAST 的列表达式。"""
+ if col.upper() == "NULL":
+ base = "NULL"
+ else:
+ is_expr = not col.isidentifier() or "->" in col or "#>>" in col or "::" in col or "'" in col
+ base = col if is_expr else f'"{col}"'
+ if cast_type:
+ cast_lower = cast_type.lower()
+ if cast_lower in {"bigint", "integer", "numeric", "decimal"}:
+ return f"CAST(NULLIF(CAST({base} AS text), '') AS numeric):: {cast_type}"
+ if cast_lower == "timestamptz":
+ return f"({base})::timestamptz"
+ return f"{base}::{cast_type}"
+ return base
diff --git a/etl_billiards/tasks/dwd_quality_task.py b/etl_billiards/tasks/dwd_quality_task.py
new file mode 100644
index 0000000..d2df657
--- /dev/null
+++ b/etl_billiards/tasks/dwd_quality_task.py
@@ -0,0 +1,105 @@
+# -*- coding: utf-8 -*-
+"""DWD 质量核对任务:按 dwd_quality_check.md 输出行数/金额对照报表。"""
+from __future__ import annotations
+
+import json
+from datetime import datetime
+from pathlib import Path
+from typing import Any, Dict, Iterable, List, Sequence, Tuple
+
+from psycopg2.extras import RealDictCursor
+
+from .base_task import BaseTask, TaskContext
+from .dwd_load_task import DwdLoadTask
+
+
+class DwdQualityTask(BaseTask):
+ """对 ODS 与 DWD 进行行数、金额对照核查,生成 JSON 报表。"""
+
+ REPORT_PATH = Path("etl_billiards/reports/dwd_quality_report.json")
+ AMOUNT_KEYWORDS = ("amount", "money", "fee", "balance")
+
+ def get_task_code(self) -> str:
+ """返回任务编码。"""
+ return "DWD_QUALITY_CHECK"
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ """准备运行时上下文。"""
+ return {"now": datetime.now()}
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict[str, Any]:
+ """输出行数/金额差异报表到本地文件。"""
+ report: Dict[str, Any] = {
+ "generated_at": extracted["now"].isoformat(),
+ "tables": [],
+ "note": "行数/金额核对,金额字段基于列名包含 amount/money/fee/balance 的数值列自动扫描。",
+ }
+
+ with self.db.conn.cursor(cursor_factory=RealDictCursor) as cur:
+ for dwd_table, ods_table in DwdLoadTask.TABLE_MAP.items():
+ count_info = self._compare_counts(cur, dwd_table, ods_table)
+ amount_info = self._compare_amounts(cur, dwd_table, ods_table)
+ report["tables"].append(
+ {
+ "dwd_table": dwd_table,
+ "ods_table": ods_table,
+ "count": count_info,
+ "amounts": amount_info,
+ }
+ )
+
+ self.REPORT_PATH.parent.mkdir(parents=True, exist_ok=True)
+ self.REPORT_PATH.write_text(json.dumps(report, ensure_ascii=False, indent=2), encoding="utf-8")
+ self.logger.info("DWD 质检报表已生成:%s", self.REPORT_PATH)
+ return {"report_path": str(self.REPORT_PATH)}
+
+ # ---------------------- helpers ----------------------
+ def _compare_counts(self, cur, dwd_table: str, ods_table: str) -> Dict[str, Any]:
+ """统计两端行数并返回差异。"""
+ dwd_schema, dwd_name = self._split_table_name(dwd_table, default_schema="billiards_dwd")
+ ods_schema, ods_name = self._split_table_name(ods_table, default_schema="billiards_ods")
+ cur.execute(f'SELECT COUNT(1) AS cnt FROM "{dwd_schema}"."{dwd_name}"')
+ dwd_cnt = cur.fetchone()["cnt"]
+ cur.execute(f'SELECT COUNT(1) AS cnt FROM "{ods_schema}"."{ods_name}"')
+ ods_cnt = cur.fetchone()["cnt"]
+ return {"dwd": dwd_cnt, "ods": ods_cnt, "diff": dwd_cnt - ods_cnt}
+
+ def _compare_amounts(self, cur, dwd_table: str, ods_table: str) -> List[Dict[str, Any]]:
+ """扫描金额相关列,生成 ODS 与 DWD 的汇总对照。"""
+ dwd_schema, dwd_name = self._split_table_name(dwd_table, default_schema="billiards_dwd")
+ ods_schema, ods_name = self._split_table_name(ods_table, default_schema="billiards_ods")
+
+ dwd_amount_cols = self._get_numeric_amount_columns(cur, dwd_schema, dwd_name)
+ ods_amount_cols = self._get_numeric_amount_columns(cur, ods_schema, ods_name)
+ common_amount_cols = sorted(set(dwd_amount_cols) & set(ods_amount_cols))
+
+ results: List[Dict[str, Any]] = []
+ for col in common_amount_cols:
+ cur.execute(f'SELECT COALESCE(SUM("{col}"),0) AS val FROM "{dwd_schema}"."{dwd_name}"')
+ dwd_sum = cur.fetchone()["val"]
+ cur.execute(f'SELECT COALESCE(SUM("{col}"),0) AS val FROM "{ods_schema}"."{ods_name}"')
+ ods_sum = cur.fetchone()["val"]
+ results.append({"column": col, "dwd_sum": float(dwd_sum or 0), "ods_sum": float(ods_sum or 0), "diff": float(dwd_sum or 0) - float(ods_sum or 0)})
+ return results
+
+ def _get_numeric_amount_columns(self, cur, schema: str, table: str) -> List[str]:
+ """获取列名包含金额关键词的数值型字段。"""
+ cur.execute(
+ """
+ SELECT column_name
+ FROM information_schema.columns
+ WHERE table_schema = %s
+ AND table_name = %s
+ AND data_type IN ('numeric','double precision','integer','bigint','smallint','real','decimal')
+ """,
+ (schema, table),
+ )
+ cols = [r["column_name"].lower() for r in cur.fetchall()]
+ return [c for c in cols if any(key in c for key in self.AMOUNT_KEYWORDS)]
+
+ def _split_table_name(self, name: str, default_schema: str) -> Tuple[str, str]:
+ """拆分 schema 与表名,缺省使用 default_schema。"""
+ parts = name.split(".")
+ if len(parts) == 2:
+ return parts[0], parts[1]
+ return default_schema, name
diff --git a/etl_billiards/tasks/dws_build_order_summary_task.py b/etl_billiards/tasks/dws_build_order_summary_task.py
new file mode 100644
index 0000000..9b2f4db
--- /dev/null
+++ b/etl_billiards/tasks/dws_build_order_summary_task.py
@@ -0,0 +1,192 @@
+# -*- coding: utf-8 -*-
+"""Build DWS order summary table from DWD fact tables."""
+
+from __future__ import annotations
+
+from datetime import date
+from typing import Any
+
+from .base_task import BaseTask, TaskContext
+from utils.windowing import build_window_segments, calc_window_minutes
+from scripts.build_dws_order_summary import SQL_BUILD_SUMMARY
+
+
+class DwsBuildOrderSummaryTask(BaseTask):
+ """Recompute/refresh `billiards_dws.dws_order_summary` for a date window."""
+
+ def get_task_code(self) -> str:
+ return "DWS_BUILD_ORDER_SUMMARY"
+
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ base_context = self._build_context(cursor_data)
+ task_code = self.get_task_code()
+ segments = build_window_segments(
+ self.config,
+ base_context.window_start,
+ base_context.window_end,
+ tz=self.tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(base_context.window_start, base_context.window_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info("%s: 分段执行 共%s段", task_code, total_segments)
+
+ total_counts: dict = {}
+ segment_results: list[dict] = []
+ request_params_list: list[dict] = []
+ total_deleted = 0
+
+ for idx, (window_start, window_end) in enumerate(segments, start=1):
+ context = self._build_context_for_window(window_start, window_end, cursor_data)
+ self.logger.info(
+ "%s: 开始执行(%s/%s), 窗口[%s ~ %s]",
+ task_code,
+ idx,
+ total_segments,
+ context.window_start,
+ context.window_end,
+ )
+
+ try:
+ extracted = self.extract(context)
+ transformed = self.transform(extracted, context)
+ load_result = self.load(transformed, context) or {}
+ self.db.commit()
+ except Exception:
+ self.db.rollback()
+ self.logger.error("%s: 执行失败", task_code, exc_info=True)
+ raise
+
+ counts = load_result.get("counts") or {}
+ self._accumulate_counts(total_counts, counts)
+
+ extra = load_result.get("extra") or {}
+ deleted = int(extra.get("deleted") or 0)
+ total_deleted += deleted
+ request_params = load_result.get("request_params")
+ if request_params:
+ request_params_list.append(request_params)
+
+ if total_segments > 1:
+ segment_results.append(
+ {
+ "window": {
+ "start": context.window_start,
+ "end": context.window_end,
+ "minutes": context.window_minutes,
+ },
+ "counts": counts,
+ "extra": extra,
+ }
+ )
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+ result = {"status": "SUCCESS", "counts": total_counts}
+ result["window"] = {
+ "start": overall_start,
+ "end": overall_end,
+ "minutes": calc_window_minutes(overall_start, overall_end),
+ }
+ if segment_results:
+ result["segments"] = segment_results
+ if request_params_list:
+ result["request_params"] = request_params_list[0] if len(request_params_list) == 1 else request_params_list
+ if total_deleted:
+ result["extra"] = {"deleted": total_deleted}
+ self.logger.info("%s: 完成, 统计=%s", task_code, total_counts)
+ return result
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ store_id = int(self.config.get("app.store_id"))
+
+ full_refresh = bool(self.config.get("dws.order_summary.full_refresh", False))
+ site_id = self.config.get("dws.order_summary.site_id", store_id)
+ if site_id in ("", None, "null", "NULL"):
+ site_id = None
+
+ start_date = self.config.get("dws.order_summary.start_date")
+ end_date = self.config.get("dws.order_summary.end_date")
+ if not full_refresh:
+ if not start_date:
+ start_date = context.window_start.date()
+ if not end_date:
+ end_date = context.window_end.date()
+ else:
+ start_date = None
+ end_date = None
+
+ delete_before_insert = bool(self.config.get("dws.order_summary.delete_before_insert", True))
+ return {
+ "site_id": site_id,
+ "start_date": start_date,
+ "end_date": end_date,
+ "full_refresh": full_refresh,
+ "delete_before_insert": delete_before_insert,
+ }
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict:
+ sql_params = {
+ "site_id": extracted["site_id"],
+ "start_date": extracted["start_date"],
+ "end_date": extracted["end_date"],
+ }
+ request_params = {
+ "site_id": extracted["site_id"],
+ "start_date": _jsonable_date(extracted["start_date"]),
+ "end_date": _jsonable_date(extracted["end_date"]),
+ }
+
+ with self.db.conn.cursor() as cur:
+ cur.execute("SELECT to_regclass('billiards_dws.dws_order_summary') AS reg;")
+ row = cur.fetchone()
+ reg = row[0] if row else None
+ if not reg:
+ raise RuntimeError("DWS 表不存在:请先运行任务 INIT_DWS_SCHEMA")
+
+ deleted = 0
+ if extracted["delete_before_insert"]:
+ if extracted["full_refresh"] and extracted["site_id"] is None:
+ cur.execute("TRUNCATE TABLE billiards_dws.dws_order_summary;")
+ self.logger.info("DWS订单汇总: 已清空 billiards_dws.dws_order_summary")
+ else:
+ delete_sql = "DELETE FROM billiards_dws.dws_order_summary WHERE 1=1"
+ delete_args: list[Any] = []
+ if extracted["site_id"] is not None:
+ delete_sql += " AND site_id = %s"
+ delete_args.append(extracted["site_id"])
+ if extracted["start_date"] is not None:
+ delete_sql += " AND order_date >= %s"
+ delete_args.append(_as_date(extracted["start_date"]))
+ if extracted["end_date"] is not None:
+ delete_sql += " AND order_date <= %s"
+ delete_args.append(_as_date(extracted["end_date"]))
+ cur.execute(delete_sql, delete_args)
+ deleted = cur.rowcount
+ self.logger.info("DWS订单汇总: 删除=%s 语句=%s", deleted, delete_sql)
+
+ cur.execute(SQL_BUILD_SUMMARY, sql_params)
+ affected = cur.rowcount
+
+ return {
+ "counts": {"fetched": 0, "inserted": affected, "updated": 0, "skipped": 0, "errors": 0},
+ "request_params": request_params,
+ "extra": {"deleted": deleted},
+ }
+
+
+def _as_date(v: Any) -> date:
+ if isinstance(v, date):
+ return v
+ return date.fromisoformat(str(v))
+
+
+def _jsonable_date(v: Any):
+ if v is None:
+ return None
+ if isinstance(v, date):
+ return v.isoformat()
+ return str(v)
diff --git a/etl_billiards/tasks/init_dwd_schema_task.py b/etl_billiards/tasks/init_dwd_schema_task.py
new file mode 100644
index 0000000..fa92aae
--- /dev/null
+++ b/etl_billiards/tasks/init_dwd_schema_task.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+"""初始化 DWD Schema:执行 schema_dwd_doc.sql,可选先 DROP SCHEMA。"""
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any
+
+from .base_task import BaseTask, TaskContext
+
+
+class InitDwdSchemaTask(BaseTask):
+ """通过调度执行 DWD schema 初始化。"""
+
+ def get_task_code(self) -> str:
+ """返回任务编码。"""
+ return "INIT_DWD_SCHEMA"
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ """读取 DWD SQL 文件与参数。"""
+ base_dir = Path(__file__).resolve().parents[1] / "database"
+ dwd_path = Path(self.config.get("schema.dwd_file", base_dir / "schema_dwd_doc.sql"))
+ if not dwd_path.exists():
+ raise FileNotFoundError(f"未找到 DWD schema 文件: {dwd_path}")
+
+ drop_first = self.config.get("dwd.drop_schema_first", False)
+ return {"dwd_sql": dwd_path.read_text(encoding="utf-8"), "dwd_file": str(dwd_path), "drop_first": drop_first}
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict:
+ """可选 DROP schema,再执行 DWD DDL。"""
+ with self.db.conn.cursor() as cur:
+ if extracted["drop_first"]:
+ cur.execute("DROP SCHEMA IF EXISTS billiards_dwd CASCADE;")
+ self.logger.info("已执行 DROP SCHEMA billiards_dwd CASCADE")
+ self.logger.info("执行 DWD schema 文件: %s", extracted["dwd_file"])
+ cur.execute(extracted["dwd_sql"])
+ return {"executed": 1, "files": [extracted["dwd_file"]]}
diff --git a/etl_billiards/tasks/init_dws_schema_task.py b/etl_billiards/tasks/init_dws_schema_task.py
new file mode 100644
index 0000000..8da483a
--- /dev/null
+++ b/etl_billiards/tasks/init_dws_schema_task.py
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+"""Initialize DWS schema (billiards_dws)."""
+
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any
+
+from .base_task import BaseTask, TaskContext
+
+
+class InitDwsSchemaTask(BaseTask):
+ """Apply DWS schema SQL."""
+
+ def get_task_code(self) -> str:
+ return "INIT_DWS_SCHEMA"
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ base_dir = Path(__file__).resolve().parents[1] / "database"
+ dws_path = Path(self.config.get("schema.dws_file", base_dir / "schema_dws.sql"))
+ if not dws_path.exists():
+ raise FileNotFoundError(f"未找到 DWS schema 文件: {dws_path}")
+ drop_first = bool(self.config.get("dws.drop_schema_first", False))
+ return {"dws_sql": dws_path.read_text(encoding="utf-8"), "dws_file": str(dws_path), "drop_first": drop_first}
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict:
+ with self.db.conn.cursor() as cur:
+ if extracted["drop_first"]:
+ cur.execute("DROP SCHEMA IF EXISTS billiards_dws CASCADE;")
+ self.logger.info("已执行 DROP SCHEMA billiards_dws CASCADE")
+ self.logger.info("执行 DWS schema 文件: %s", extracted["dws_file"])
+ cur.execute(extracted["dws_sql"])
+ return {"executed": 1, "files": [extracted["dws_file"]]}
+
diff --git a/etl_billiards/tasks/init_schema_task.py b/etl_billiards/tasks/init_schema_task.py
new file mode 100644
index 0000000..9e98caa
--- /dev/null
+++ b/etl_billiards/tasks/init_schema_task.py
@@ -0,0 +1,73 @@
+# -*- coding: utf-8 -*-
+"""任务:初始化运行环境,执行 ODS 与 etl_admin 的 DDL,并准备日志/导出目录。"""
+from __future__ import annotations
+
+from pathlib import Path
+from typing import Any
+
+from .base_task import BaseTask, TaskContext
+
+
+class InitOdsSchemaTask(BaseTask):
+ """通过调度执行初始化:创建必要目录,执行 ODS 与 etl_admin 的 DDL。"""
+
+ def get_task_code(self) -> str:
+ """返回任务编码。"""
+ return "INIT_ODS_SCHEMA"
+
+ def extract(self, context: TaskContext) -> dict[str, Any]:
+ """读取 SQL 文件路径,收集需创建的目录。"""
+ base_dir = Path(__file__).resolve().parents[1] / "database"
+ ods_path = Path(self.config.get("schema.ods_file", base_dir / "schema_ODS_doc.sql"))
+ admin_path = Path(self.config.get("schema.etl_admin_file", base_dir / "schema_etl_admin.sql"))
+ if not ods_path.exists():
+ raise FileNotFoundError(f"找不到 ODS schema 文件: {ods_path}")
+ if not admin_path.exists():
+ raise FileNotFoundError(f"找不到 etl_admin schema 文件: {admin_path}")
+
+ log_root = Path(self.config.get("io.log_root") or self.config["io"]["log_root"])
+ export_root = Path(self.config.get("io.export_root") or self.config["io"]["export_root"])
+ fetch_root = Path(self.config.get("pipeline.fetch_root") or self.config["pipeline"]["fetch_root"])
+ ingest_dir = Path(self.config.get("pipeline.ingest_source_dir") or fetch_root)
+
+ return {
+ "ods_sql": ods_path.read_text(encoding="utf-8"),
+ "admin_sql": admin_path.read_text(encoding="utf-8"),
+ "ods_file": str(ods_path),
+ "admin_file": str(admin_path),
+ "dirs": [log_root, export_root, fetch_root, ingest_dir],
+ }
+
+ def load(self, extracted: dict[str, Any], context: TaskContext) -> dict:
+ """执行 DDL 并创建必要目录。
+
+ 安全提示:
+ ODS DDL 文件可能携带头部说明或异常注释,为避免因非 SQL 文本导致执行失败,这里会做一次轻量清洗后再执行。
+ """
+ for d in extracted["dirs"]:
+ Path(d).mkdir(parents=True, exist_ok=True)
+ self.logger.info("已确保目录存在: %s", d)
+
+ # 处理 ODS SQL:去掉头部说明行,以及易出错的 COMMENT ON 行(如 CamelCase 未加引号)
+ ods_sql_raw: str = extracted["ods_sql"]
+ drop_idx = ods_sql_raw.find("DROP SCHEMA")
+ if drop_idx > 0:
+ ods_sql_raw = ods_sql_raw[drop_idx:]
+ cleaned_lines: list[str] = []
+ for line in ods_sql_raw.splitlines():
+ if line.strip().upper().startswith("COMMENT ON "):
+ continue
+ cleaned_lines.append(line)
+ ods_sql = "\n".join(cleaned_lines)
+
+ with self.db.conn.cursor() as cur:
+ self.logger.info("执行 etl_admin schema 文件: %s", extracted["admin_file"])
+ cur.execute(extracted["admin_sql"])
+ self.logger.info("执行 ODS schema 文件: %s", extracted["ods_file"])
+ cur.execute(ods_sql)
+
+ return {
+ "executed": 2,
+ "files": [extracted["admin_file"], extracted["ods_file"]],
+ "dirs_prepared": [str(p) for p in extracted["dirs"]],
+ }
diff --git a/etl_billiards/tasks/manual_ingest_task.py b/etl_billiards/tasks/manual_ingest_task.py
index 695f519..15ffa7d 100644
--- a/etl_billiards/tasks/manual_ingest_task.py
+++ b/etl_billiards/tasks/manual_ingest_task.py
@@ -1,58 +1,85 @@
# -*- coding: utf-8 -*-
-"""Manual ingestion task that replays archived JSON into ODS tables."""
+"""手工示例数据灌入:按 schema_ODS_doc.sql 的表结构写入 ODS。"""
from __future__ import annotations
import json
import os
from datetime import datetime
-from typing import Iterable, Iterator
+from typing import Any, Iterable
+
+from psycopg2.extras import Json, execute_values
from .base_task import BaseTask
class ManualIngestTask(BaseTask):
- """
- Load archived API responses (tests/source-data-doc) into billiards_ods.* tables.
- Used when upstream API is unavailable and we need to replay captured payloads.
- """
+ """本地示例 JSON 灌入 ODS,确保表名/主键/插入列与 schema_ODS_doc.sql 对齐。"""
- # 仅保留已确认的新表映射,其余表待逐一校准后再添加
FILE_MAPPING: list[tuple[tuple[str, ...], str]] = [
- (("助教账号",), "billiards_ods.assistant_accounts_master"),
- (("助教流水",), "billiards_ods.assistant_service_records"),
- (("助教废除", "助教作废"), "billiards_ods.assistant_cancellation_records"),
- (("库存变化记录1",), "billiards_ods.goods_stock_movements"),
- (("库存汇总", "库存汇总记录"), "billiards_ods.goods_stock_summary"),
- (("团购套餐", "套餐定义"), "billiards_ods.group_buy_packages"),
- (("团购核销", "套餐使用", "团购使用"), "billiards_ods.group_buy_redemption_records"),
- (("余额变动", "余额变更"), "billiards_ods.member_balance_changes"),
- (("会员档案", "会员列表"), "billiards_ods.member_profiles"),
- (("储值卡", "会员储值卡"), "billiards_ods.member_stored_value_cards"),
- (("支付记录", "支付流水"), "billiards_ods.payment_transactions"),
- (("平台验券", "团购验券", "平台券核销"), "billiards_ods.platform_coupon_redemption_records"),
- (("充值结算", "充值记录"), "billiards_ods.recharge_settlements"),
- (("退款流水", "退款记录"), "billiards_ods.refund_transactions"),
- (("结账记录", "结算记录"), "billiards_ods.settlement_records"),
- (("小票详情", "结账小票"), "billiards_ods.settlement_ticket_details"),
- (("台桌列表", "台桌维表"), "billiards_ods.site_tables_master"),
- (("商品分类树", "库存分类"), "billiards_ods.stock_goods_category_tree"),
- (("门店商品档案",), "billiards_ods.store_goods_master"),
- (("门店商品销售", "商品销售流水"), "billiards_ods.store_goods_sales_records"),
- (("台费折扣", "台费调账"), "billiards_ods.table_fee_discount_records"),
- (("台费流水", "台费计费"), "billiards_ods.table_fee_transactions"),
- (("租户商品档案", "商品档案"), "billiards_ods.tenant_goods_master"),
+ (("member_profiles",), "billiards_ods.member_profiles"),
+ (("member_balance_changes",), "billiards_ods.member_balance_changes"),
+ (("member_stored_value_cards",), "billiards_ods.member_stored_value_cards"),
+ (("recharge_settlements",), "billiards_ods.recharge_settlements"),
+ (("settlement_records",), "billiards_ods.settlement_records"),
+ (("assistant_cancellation_records",), "billiards_ods.assistant_cancellation_records"),
+ (("assistant_accounts_master",), "billiards_ods.assistant_accounts_master"),
+ (("assistant_service_records",), "billiards_ods.assistant_service_records"),
+ (("site_tables_master",), "billiards_ods.site_tables_master"),
+ (("table_fee_discount_records",), "billiards_ods.table_fee_discount_records"),
+ (("table_fee_transactions",), "billiards_ods.table_fee_transactions"),
+ (("goods_stock_movements",), "billiards_ods.goods_stock_movements"),
+ (("stock_goods_category_tree",), "billiards_ods.stock_goods_category_tree"),
+ (("goods_stock_summary",), "billiards_ods.goods_stock_summary"),
+ (("payment_transactions",), "billiards_ods.payment_transactions"),
+ (("refund_transactions",), "billiards_ods.refund_transactions"),
+ (("platform_coupon_redemption_records",), "billiards_ods.platform_coupon_redemption_records"),
+ (("group_buy_redemption_records",), "billiards_ods.group_buy_redemption_records"),
+ (("group_buy_packages",), "billiards_ods.group_buy_packages"),
+ (("settlement_ticket_details",), "billiards_ods.settlement_ticket_details"),
+ (("store_goods_master",), "billiards_ods.store_goods_master"),
+ (("tenant_goods_master",), "billiards_ods.tenant_goods_master"),
+ (("store_goods_sales_records",), "billiards_ods.store_goods_sales_records"),
]
- WRAPPER_META_KEYS = {"code", "message", "msg", "success", "error", "status"}
+
+ TABLE_SPECS: dict[str, dict[str, Any]] = {
+ "billiards_ods.member_profiles": {"pk": "id"},
+ "billiards_ods.member_balance_changes": {"pk": "id"},
+ "billiards_ods.member_stored_value_cards": {"pk": "id"},
+ "billiards_ods.recharge_settlements": {"pk": "id"},
+ "billiards_ods.settlement_records": {"pk": "id"},
+ "billiards_ods.assistant_cancellation_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.assistant_accounts_master": {"pk": "id"},
+ "billiards_ods.assistant_service_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.site_tables_master": {"pk": "id"},
+ "billiards_ods.table_fee_discount_records": {"pk": "id", "json_cols": ["siteProfile", "tableProfile"]},
+ "billiards_ods.table_fee_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.goods_stock_movements": {"pk": "siteGoodsStockId"},
+ "billiards_ods.stock_goods_category_tree": {"pk": "id", "json_cols": ["categoryBoxes"]},
+ "billiards_ods.goods_stock_summary": {"pk": "siteGoodsId"},
+ "billiards_ods.payment_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.refund_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.platform_coupon_redemption_records": {"pk": "id"},
+ "billiards_ods.tenant_goods_master": {"pk": "id"},
+ "billiards_ods.group_buy_packages": {"pk": "id"},
+ "billiards_ods.group_buy_redemption_records": {"pk": "id"},
+ "billiards_ods.settlement_ticket_details": {
+ "pk": "orderSettleId",
+ "json_cols": ["memberProfile", "orderItem", "tenantMemberCardLogs"],
+ },
+ "billiards_ods.store_goods_master": {"pk": "id"},
+ "billiards_ods.store_goods_sales_records": {"pk": "id"},
+ }
def get_task_code(self) -> str:
+ """返回任务编码。"""
return "MANUAL_INGEST"
- def execute(self) -> dict:
- self.logger.info("Starting Manual Ingest Task")
-
- data_dir = self.config.get(
- "manual.data_dir",
- r"c:\dev\LLTQ\ETL\feiqiu-ETL\etl_billiards\tests\testdata_json",
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ """从目录读取 JSON,按表定义批量入库(按文件提交事务,避免长事务导致连接不稳定)。"""
+ data_dir = (
+ self.config.get("manual.data_dir")
+ or self.config.get("pipeline.ingest_source_dir")
+ or os.path.join("tests", "testdata_json")
)
if not os.path.exists(data_dir):
self.logger.error("Data directory not found: %s", data_dir)
@@ -60,10 +87,15 @@ class ManualIngestTask(BaseTask):
counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+ include_files_cfg = self.config.get("manual.include_files") or []
+ include_files = {str(x).strip().lower() for x in include_files_cfg if str(x).strip()} if include_files_cfg else set()
+
for filename in sorted(os.listdir(data_dir)):
if not filename.endswith(".json"):
continue
-
+ stem = os.path.splitext(filename)[0].lower()
+ if include_files and stem not in include_files:
+ continue
filepath = os.path.join(data_dir, filename)
try:
with open(filepath, "r", encoding="utf-8") as fh:
@@ -73,929 +105,299 @@ class ManualIngestTask(BaseTask):
self.logger.exception("Failed to read %s", filename)
continue
- if not isinstance(raw_entries, list):
- raw_entries = [raw_entries]
-
- records = self._normalize_records(raw_entries)
+ entries = raw_entries if isinstance(raw_entries, list) else [raw_entries]
+ records = self._extract_records(entries)
if not records:
counts["skipped"] += 1
continue
- target_table = self._match_by_filename(filename) or self._match_by_content(
- records, raw_entries
- )
+ target_table = self._match_by_filename(filename)
if not target_table:
self.logger.warning("No mapping found for file: %s", filename)
counts["skipped"] += 1
continue
self.logger.info("Ingesting %s into %s", filename, target_table)
-
try:
- rows = []
- for record in records:
- site_id = self._extract_store_id(record) or self.config.get(
- "app.store_id"
- )
- pk_value = self._extract_pk(record, target_table)
- pk_tuple = self._ensure_tuple(pk_value)
- if not all(value not in (None, "") for value in pk_tuple):
- continue
-
- row = {
- "site_id": site_id,
- "payload": json.dumps(record, ensure_ascii=False),
- "source_file": filename,
- "fetched_at": datetime.now(),
- }
- for column, value in zip(
- self._get_conflict_columns(target_table), pk_tuple
- ):
- row[column] = value
- self._enrich_row(row, record, target_table)
- rows.append(row)
-
- if rows:
- self._bulk_insert(target_table, rows)
- counts["inserted"] += len(rows)
- else:
- counts["skipped"] += 1
- counts["fetched"] += 1
-
+ inserted, updated, row_errors = self._ingest_table(target_table, records, filename)
+ counts["inserted"] += inserted
+ counts["updated"] += updated
+ counts["fetched"] += len(records)
+ counts["errors"] += row_errors
+ # 每个文件一次提交:降低单次事务体积,避免长事务/连接异常导致整体回滚失败。
+ self.db.commit()
except Exception:
counts["errors"] += 1
self.logger.exception("Error processing %s", filename)
- self.db.rollback()
+ try:
+ self.db.rollback()
+ except Exception:
+ pass
+ # 若连接已断开,后续文件无法继续,直接抛出让上层处理(重连/重跑)。
+ if getattr(self.db.conn, "closed", 0):
+ raise
+ continue
- try:
- self.db.commit()
- except Exception:
- self.db.rollback()
- raise
+ return {"status": "SUCCESS", "counts": counts}
- return self._build_result("SUCCESS", counts)
-
- # ------------------------------------------------------------------ helpers
def _match_by_filename(self, filename: str) -> str | None:
+ """根据文件名关键字匹配目标表。"""
for keywords, table in self.FILE_MAPPING:
if any(keyword and keyword in filename for keyword in keywords):
return table
return None
- def _match_by_content(
- self, records: list[dict], raw_entries: list[dict]
- ) -> str | None:
- """
- Map content to PRD ODS tables.
- """
- sample_record = records[0] if records else None
- wrapper = self._extract_sample(raw_entries)
- data_node = wrapper.get("data") if isinstance(wrapper, dict) else None
- data_keys = set(data_node.keys()) if isinstance(data_node, dict) else set()
- record_keys = set(sample_record.keys()) if isinstance(sample_record, dict) else set()
-
- # Data node based hints
- if "tenantMemberInfos" in data_keys:
- return "billiards_ods.ods_member_profile"
- if "tenantMemberCards" in data_keys:
- return "billiards_ods.ods_member_card"
- if "queryDeliveryRecordsList" in data_keys:
- return "billiards_ods.ods_inventory_change"
- if "goodsStockA" in data_keys or "rangeStartStock" in data_keys:
- return "billiards_ods.ods_inventory_stock"
- if "goodsCategoryList" in data_keys:
- return "billiards_ods.ods_goods_category"
- if "orderAssistantDetails" in data_keys:
- return "billiards_ods.ods_assistant_service_log"
- if "abolitionAssistants" in data_keys:
- return "billiards_ods.ods_assistant_cancel_log"
- if "siteTableUseDetailsList" in data_keys:
- return "billiards_ods.ods_table_use_log"
- if "taiFeeAdjustInfos" in data_keys:
- return "billiards_ods.ods_table_fee_adjust"
- if "orderGoodsLedgers" in data_keys or "orderGoodsList" in data_keys:
- return "billiards_ods.ods_store_sale_item"
- if "tenantGoodsList" in data_keys:
- return "billiards_ods.ods_store_product"
- if "packageCouponList" in data_keys:
- return "billiards_ods.ods_group_package"
- if "settleList" in data_keys and "total" in data_keys:
- return "billiards_ods.ods_order_settle"
-
- # Record key based hints
- if sample_record:
- if {"pay_amount", "pay_status"} <= record_keys or {"payAmount", "payStatus"} <= record_keys:
- return "billiards_ods.ods_payment_record"
- if "refundAmount" in record_keys or "refund_amount" in record_keys:
- return "billiards_ods.ods_refund_record"
- if "orderSettleId" in record_keys or "order_settle_id" in record_keys:
- return "billiards_ods.ods_order_receipt_detail"
- if "coupon_channel" in record_keys or "groupPackageId" in record_keys:
- return "billiards_ods.ods_platform_coupon_log"
- if "packageId" in record_keys or "package_id" in record_keys:
- return "billiards_ods.ods_group_package_log"
- if "memberCardId" in record_keys or "cardId" in record_keys:
- return "billiards_ods.ods_member_card"
- if "memberId" in record_keys:
- return "billiards_ods.ods_member_profile"
- if "siteGoodsId" in record_keys and "currentStock" in record_keys:
- return "billiards_ods.ods_inventory_stock"
- if "goodsId" in record_keys:
- return "billiards_ods.ods_product"
-
- return None
-
- def _extract_sample(self, payloads: Iterable[dict]) -> dict:
- for item in payloads:
- if isinstance(item, dict):
- return item
- return {}
-
- def _normalize_records(self, payloads: list[dict]) -> list[dict]:
+ def _extract_records(self, raw_entries: Iterable[Any]) -> list[dict]:
+ """兼容多层 data/list 包装,抽取记录列表。"""
records: list[dict] = []
- for payload in payloads:
- records.extend(self._unwrap_payload(payload))
+ for entry in raw_entries:
+ if isinstance(entry, dict):
+ preferred = entry
+ if "data" in entry and not any(k not in {"data", "code"} for k in entry.keys()):
+ preferred = entry["data"]
+ data = preferred
+ if isinstance(data, dict):
+ # 特殊处理 settleList(充值、结算记录):展开 data.settleList 下的 settleList,抛弃上层 siteProfile
+ if "settleList" in data:
+ settle_list_val = data.get("settleList")
+ if isinstance(settle_list_val, dict):
+ settle_list_iter = [settle_list_val]
+ elif isinstance(settle_list_val, list):
+ settle_list_iter = settle_list_val
+ else:
+ settle_list_iter = []
+
+ handled = False
+ for item in settle_list_iter or []:
+ if not isinstance(item, dict):
+ continue
+ inner = item.get("settleList")
+ merged = dict(inner) if isinstance(inner, dict) else dict(item)
+ # 保留 siteProfile 供后续字段补充,但不落库
+ site_profile = data.get("siteProfile")
+ if isinstance(site_profile, dict):
+ merged.setdefault("siteProfile", site_profile)
+ records.append(merged)
+ handled = True
+ if handled:
+ continue
+
+ list_used = False
+ for v in data.values():
+ if isinstance(v, list) and v and isinstance(v[0], dict):
+ records.extend(v)
+ list_used = True
+ break
+ if list_used:
+ continue
+ if isinstance(data, list) and data and isinstance(data[0], dict):
+ records.extend(data)
+ elif isinstance(data, dict):
+ records.append(data)
+ elif isinstance(entry, list):
+ records.extend([item for item in entry if isinstance(item, dict)])
return records
- def _unwrap_payload(self, payload) -> list[dict]:
- if isinstance(payload, dict):
- data_node = payload.get("data")
- extra_keys = set(payload.keys()) - {"data"} - self.WRAPPER_META_KEYS
- if isinstance(data_node, dict) and not extra_keys:
- flattened: list[dict] = []
- found_list = False
- for value in data_node.values():
- if isinstance(value, list):
- flattened.extend(value)
- found_list = True
- if found_list:
- return flattened
- return [data_node]
- return [payload]
+ def _get_table_columns(self, table: str) -> list[tuple[str, str, str]]:
+ """查询 information_schema,获取目标表列信息。"""
+ cache = getattr(self, "_table_columns_cache", {})
+ if table in cache:
+ return cache[table]
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT column_name, data_type, udt_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """
+ with self.db.conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ cols = [(r[0], (r[1] or "").lower(), (r[2] or "").lower()) for r in cur.fetchall()]
+ cache[table] = cols
+ self._table_columns_cache = cache
+ return cols
- if isinstance(payload, list):
- flattened: list[dict] = []
- for item in payload:
- flattened.extend(self._unwrap_payload(item))
- return flattened
+ def _ingest_table(self, table: str, records: list[dict], source_file: str) -> tuple[int, int, int]:
+ """
+ 构建 INSERT/ON CONFLICT 语句并批量执行(优先向量化,小批次提交)。
- return []
+ 设计目标:
+ - 控制单条 SQL 体积(避免一次性 VALUES 过大导致服务端 backend 被 OOM/异常终止);
+ - 发生异常时,可降级逐行并用 SAVEPOINT 跳过异常行;
+ - 统计口径偏“尽量可跑通”,插入/更新计数为近似值(不强依赖 RETURNING)。
+ """
+ spec = self.TABLE_SPECS.get(table)
+ if not spec:
+ raise ValueError(f"No table spec for {table}")
- def _extract_store_id(self, item: dict):
- """Extract site_id from record/siteProfile wrappers."""
- site_profile = item.get("siteProfile") or item.get("site_profile")
- if isinstance(site_profile, dict) and site_profile.get("id"):
- return site_profile["id"]
+ pk_col = spec.get("pk")
+ json_cols = set(spec.get("json_cols", []))
+ json_cols_lower = {c.lower() for c in json_cols}
- for key in ("site_id", "siteId", "register_site_id"):
- if item.get(key):
- return item[key]
-
- data_node = item.get("data")
- if isinstance(data_node, dict):
- return data_node.get("siteId") or data_node.get("site_id")
-
- return self.config.get("app.store_id")
-
- def _extract_pk(self, item: dict, table: str):
- if "ods_order_receipt_detail" in table:
- return item.get("orderSettleId") or item.get("order_settle_id") or item.get("id")
- if "ods_order_settle" in table:
- settle = item.get("settleList") or item.get("settle") or item
- if isinstance(settle, dict):
- return settle.get("id") or settle.get("settleId") or item.get("id")
- return item.get("id")
-
- if "ods_payment_record" in table:
- return item.get("payId") or item.get("id")
-
- if "ods_refund_record" in table:
- return item.get("refundId") or item.get("id")
-
- if "ods_platform_coupon_log" in table:
- return item.get("couponId") or item.get("id")
-
- if "ods_assistant_service_log" in table or "ods_table_use_log" in table:
- return item.get("ledgerId") or item.get("ledger_id") or item.get("id")
-
- if "ods_assistant_cancel_log" in table:
- return item.get("cancel_id") or item.get("cancelId") or item.get("abolishId") or item.get("id")
-
- if "ods_store_sale_item" in table:
- return (
- item.get("sale_item_id")
- or item.get("saleItemId")
- or item.get("orderGoodsId")
- or item.get("order_goods_id")
- or item.get("id")
- )
-
- if "ods_inventory_change" in table:
- return item.get("siteGoodsStockId") or item.get("id")
-
- if "ods_inventory_stock" in table:
- return (
- item.get("siteGoodsId")
- or item.get("id"),
- item.get("snapshotKey") or item.get("snapshot_key") or "default",
- )
-
- if "ods_member_card" in table:
- return item.get("cardId") or item.get("memberCardId") or item.get("id")
-
- if "ods_member_profile" in table:
- return item.get("memberId") or item.get("id")
-
- if "ods_group_package_log" in table:
- return item.get("usage_id") or item.get("usageId") or item.get("couponId") or item.get("id")
-
- if "ods_group_package" in table:
- return item.get("package_id") or item.get("packageId") or item.get("groupPackageId") or item.get("id")
-
- if "ods_goods_category" in table:
- return item.get("category_id") or item.get("categoryId") or item.get("id")
-
- if "ods_table_fee_adjust" in table:
- return item.get("adjust_id") or item.get("adjustId") or item.get("id")
-
- if "ods_table_info" in table:
- return item.get("table_id") or item.get("tableId") or item.get("id")
-
- if "ods_assistant_account" in table:
- return item.get("assistantId") or item.get("assistant_id") or item.get("id")
-
- if "ods_store_product" in table:
- return item.get("siteGoodsId") or item.get("site_goods_id") or item.get("id")
-
- if "ods_product" in table:
- return item.get("goodsId") or item.get("goods_id") or item.get("id")
-
- if "ods_balance_change" in table:
- return item.get("change_id") or item.get("changeId") or item.get("id")
-
- if "ods_recharge_record" in table:
- return item.get("recharge_id") or item.get("rechargeId") or item.get("id")
-
- return item.get("id")
-
- def _get_conflict_columns(self, table: str) -> list[str]:
- if "ods_order_receipt_detail" in table:
- return ["order_settle_id"]
- if "ods_payment_record" in table:
- return ["pay_id"]
- if "ods_refund_record" in table:
- return ["refund_id"]
- if "ods_platform_coupon_log" in table:
- return ["coupon_id"]
- if "ods_assistant_service_log" in table or "ods_table_use_log" in table:
- return ["ledger_id"]
- if "ods_assistant_cancel_log" in table:
- return ["cancel_id"]
- if "ods_store_sale_item" in table:
- return ["sale_item_id"]
- if "ods_order_settle" in table:
- return ["order_settle_id"]
- if "ods_inventory_change" in table:
- return ["change_id"]
- if "ods_inventory_stock" in table:
- return ["site_goods_id", "snapshot_key"]
- if "ods_member_card" in table:
- return ["card_id"]
- if "ods_member_profile" in table:
- return ["member_id"]
- if "ods_group_package_log" in table:
- return ["usage_id"]
- if "ods_group_package" in table:
- return ["package_id"]
- if "ods_goods_category" in table:
- return ["category_id"]
- if "ods_table_info" in table:
- return ["table_id"]
- if "ods_table_fee_adjust" in table:
- return ["adjust_id"]
- if "ods_assistant_account" in table:
- return ["assistant_id"]
- if "ods_store_product" in table:
- return ["site_goods_id"]
- if "ods_product" in table:
- return ["goods_id"]
- if "ods_balance_change" in table:
- return ["change_id"]
- if "ods_recharge_record" in table:
- return ["recharge_id"]
- return ["id"]
-
- def _enrich_row(self, row: dict, record: dict, table: str):
- """Best-effort populate important columns from payload for PRD ODS schema."""
- def pick(obj, *keys):
- for k in keys:
- if isinstance(obj, dict) and obj.get(k) not in (None, ""):
- return obj.get(k)
- return None
- def to_bool(value):
- if value in (None, ""):
- return None
+ columns_info = self._get_table_columns(table)
+ columns = [c[0] for c in columns_info]
+ db_json_cols_lower = {
+ c[0].lower() for c in columns_info if c[1] in ("json", "jsonb") or c[2] in ("json", "jsonb")
+ }
+ pk_col_db = None
+ if pk_col:
+ pk_col_db = next((c for c in columns if c.lower() == pk_col.lower()), pk_col)
+ pk_index = None
+ if pk_col_db:
try:
- return bool(int(value))
+ pk_index = next(i for i, c in enumerate(columns_info) if c[0] == pk_col_db)
except Exception:
- if isinstance(value, bool):
- return value
- return None
- def to_int(value):
- if value in (None, ""):
- return None
+ pk_index = None
+
+ col_list = ", ".join(f'"{c}"' for c in columns)
+ sql_prefix = f"INSERT INTO {table} ({col_list}) VALUES %s"
+ if pk_col_db:
+ update_cols = [c for c in columns if c != pk_col_db]
+ set_clause = ", ".join(f'"{c}"=EXCLUDED."{c}"' for c in update_cols)
+ sql_prefix += f' ON CONFLICT ("{pk_col_db}") DO UPDATE SET {set_clause}'
+
+ params = []
+ now = datetime.now()
+ json_dump = lambda v: json.dumps(v, ensure_ascii=False) # noqa: E731
+ for rec in records:
+ merged_rec = rec if isinstance(rec, dict) else {}
+ data_part = merged_rec.get("data")
+ while isinstance(data_part, dict):
+ merged_rec = {**data_part, **merged_rec}
+ data_part = data_part.get("data")
+
+ # 针对充值/结算,补齐 siteProfile 中的店铺信息
+ if table in {
+ "billiards_ods.recharge_settlements",
+ "billiards_ods.settlement_records",
+ }:
+ site_profile = merged_rec.get("siteProfile") or merged_rec.get("site_profile")
+ if isinstance(site_profile, dict):
+ merged_rec.setdefault("tenantid", site_profile.get("tenant_id") or site_profile.get("tenantId"))
+ merged_rec.setdefault("siteid", site_profile.get("id") or site_profile.get("siteId"))
+ merged_rec.setdefault("sitename", site_profile.get("shop_name") or site_profile.get("siteName"))
+
+ pk_val = self._get_value_case_insensitive(merged_rec, pk_col) if pk_col else None
+ if pk_col and (pk_val is None or pk_val == ""):
+ continue
+
+ row_vals = []
+ for col_name, data_type, udt in columns_info:
+ col_lower = col_name.lower()
+ if col_lower == "payload":
+ row_vals.append(Json(rec, dumps=json_dump))
+ continue
+ if col_lower == "source_file":
+ row_vals.append(source_file)
+ continue
+ if col_lower == "fetched_at":
+ row_vals.append(merged_rec.get(col_name, now))
+ continue
+
+ value = self._normalize_scalar(self._get_value_case_insensitive(merged_rec, col_name))
+
+ if col_lower in json_cols_lower or col_lower in db_json_cols_lower:
+ row_vals.append(Json(value, dumps=json_dump) if value is not None else None)
+ continue
+
+ casted = self._cast_value(value, data_type)
+ row_vals.append(casted)
+ params.append(tuple(row_vals))
+
+ if not params:
+ return 0, 0, 0
+
+ # 先尝试向量化执行(速度快);若失败,再降级逐行并用 SAVEPOINT 跳过异常行。
+ try:
+ with self.db.conn.cursor() as cur:
+ # 分批提交:降低单次事务/单次 SQL 压力,避免服务端异常中断连接。
+ affected = 0
+ chunk_size = int(self.config.get("manual.execute_values_page_size", 50) or 50)
+ chunk_size = max(1, min(chunk_size, 500))
+ for i in range(0, len(params), chunk_size):
+ chunk = params[i : i + chunk_size]
+ execute_values(cur, sql_prefix, chunk, page_size=len(chunk))
+ if cur.rowcount is not None and cur.rowcount > 0:
+ affected += int(cur.rowcount)
+ # 这里无法精确拆分 inserted/updated(除非 RETURNING),按“受影响行数≈插入”近似返回。
+ return int(affected), 0, 0
+ except Exception as exc:
+ self.logger.warning("批量入库失败,准备降级逐行处理:table=%s, err=%s", table, exc)
+ try:
+ self.db.rollback()
+ except Exception:
+ pass
+
+ inserted = 0
+ updated = 0
+ errors = 0
+ with self.db.conn.cursor() as cur:
+ for row in params:
+ cur.execute("SAVEPOINT sp_manual_ingest_row")
+ try:
+ cur.execute(sql_prefix.replace(" VALUES %s", f" VALUES ({', '.join(['%s'] * len(row))})"), row)
+ inserted += 1
+ cur.execute("RELEASE SAVEPOINT sp_manual_ingest_row")
+ except Exception as exc: # noqa: BLE001
+ errors += 1
+ try:
+ cur.execute("ROLLBACK TO SAVEPOINT sp_manual_ingest_row")
+ cur.execute("RELEASE SAVEPOINT sp_manual_ingest_row")
+ except Exception:
+ pass
+ pk_val = None
+ if pk_index is not None:
+ try:
+ pk_val = row[pk_index]
+ except Exception:
+ pk_val = None
+ self.logger.warning("跳过异常行:table=%s pk=%s err=%s", table, pk_val, exc)
+
+ return inserted, updated, errors
+
+ @staticmethod
+ def _get_value_case_insensitive(record: dict, col: str | None):
+ """忽略大小写获取值,兼容 information_schema 与 JSON 原始字段。"""
+ if record is None or col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+ @staticmethod
+ def _normalize_scalar(value):
+ """将空字符串/空 JSON 规范为 None,避免类型转换错误。"""
+ if value == "" or value == "{}" or value == "[]":
+ return None
+ return value
+
+ @staticmethod
+ def _cast_value(value, data_type: str):
+ """根据列类型做简单转换,保证批量插入兼容。"""
+ if value is None:
+ return None
+ dt = (data_type or "").lower()
+ if dt in ("integer", "bigint", "smallint"):
+ if isinstance(value, bool):
+ return int(value)
try:
return int(value)
except Exception:
return None
-
- if "ods_member_profile" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["system_member_id"] = record.get("system_member_id")
- row["register_site_id"] = record.get("register_site_id")
- row["site_name"] = record.get("site_name")
- row["member_name"] = pick(record, "name", "memberName")
- row["nickname"] = record.get("nickname")
- row["mobile"] = record.get("mobile")
- row["gender"] = record.get("sex")
- row["birthday"] = record.get("birthday")
- row["register_time"] = record.get("register_time") or record.get("registerTime")
- row["member_type_id"] = pick(record, "cardTypeId", "member_type_id")
- row["member_type_name"] = record.get("cardTypeName")
- row["member_card_grade_code"] = record.get("member_card_grade_code")
- row["status"] = pick(record, "status", "state")
- row["user_status"] = record.get("user_status")
- row["balance"] = record.get("balance")
- row["points"] = record.get("points") or record.get("point")
- row["growth_value"] = record.get("growth_value")
- row["last_visit_time"] = record.get("lastVisitTime")
- row["wechat_id"] = record.get("wechatId")
- row["alipay_id"] = record.get("alipayId")
- row["member_card_no"] = record.get("cardNo")
- row["referrer_member_id"] = record.get("referrer_member_id")
- row["remarks"] = record.get("remark")
-
- if "ods_member_card" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["member_id"] = pick(record, "memberId", "member_id")
- row["tenant_member_id"] = record.get("tenant_member_id")
- row["card_type_id"] = record.get("cardTypeId")
- row["card_type_name"] = record.get("cardTypeName")
- row["card_no"] = record.get("card_no") or record.get("cardNo")
- row["card_physics_type"] = record.get("card_physics_type")
- row["card_balance"] = record.get("balance")
- row["denomination"] = record.get("denomination")
- row["discount_rate"] = record.get("discount") or record.get("discount_rate")
- row["table_discount"] = record.get("table_discount")
- row["goods_discount"] = record.get("goods_discount")
- row["assistant_discount"] = record.get("assistant_discount")
- row["assistant_reward_discount"] = record.get("assistant_reward_discount")
- row["valid_start_date"] = record.get("validStart") or record.get("start_time")
- row["valid_end_date"] = record.get("validEnd") or record.get("end_time")
- row["disable_start_date"] = record.get("disable_start_time")
- row["disable_end_date"] = record.get("disable_end_time")
- row["last_consume_time"] = record.get("lastConsumeTime")
- row["status"] = record.get("status")
- row["is_delete"] = to_bool(record.get("is_delete"))
- row["activate_time"] = record.get("activateTime")
- row["deactivate_time"] = record.get("cancelTime")
- row["register_site_id"] = record.get("register_site_id")
- row["issuer_id"] = record.get("issuerId")
- row["issuer_name"] = record.get("issuerName")
-
- if "ods_recharge_record" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["member_id"] = pick(record, "memberId", "member_id")
- row["recharge_amount"] = record.get("amount") or record.get("rechargeAmount")
- row["gift_amount"] = record.get("giftAmount")
- row["pay_method"] = record.get("payType") or record.get("pay_method")
- row["pay_trade_no"] = record.get("payTradeNo")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["recharge_time"] = record.get("createTime") or record.get("rechargeTime")
- row["status"] = record.get("status")
- row["operator_id"] = record.get("operatorId")
- row["operator_name"] = record.get("operatorName")
-
- if "ods_balance_change" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["site_id"] = row.get("site_id") or pick(record, "siteId", "site_id")
- row["member_id"] = pick(record, "memberId", "member_id")
- row["tenant_member_id"] = record.get("tenant_member_id")
- row["tenant_member_card_id"] = record.get("tenant_member_card_id")
- row["member_name"] = record.get("memberName")
- row["member_mobile"] = record.get("memberMobile")
- row["change_amount"] = record.get("change_amount") or record.get("account_data")
- row["balance_before"] = record.get("before_balance") or record.get("before")
- row["balance_after"] = record.get("after_balance") or record.get("after")
- row["change_type"] = record.get("from_type") or record.get("type")
- row["payment_method"] = record.get("payment_method")
- row["refund_amount"] = record.get("refund_amount")
- row["relate_id"] = record.get("relate_id")
- row["register_site_id"] = record.get("register_site_id")
- row["register_site_name"] = record.get("registerSiteName")
- row["pay_site_name"] = record.get("paySiteName")
- row["remark"] = record.get("remark")
- row["operator_id"] = record.get("operatorId")
- row["operator_name"] = record.get("operatorName")
- row["change_time"] = record.get("create_time") or record.get("changeTime")
- row["is_deleted"] = to_bool(record.get("is_delete") or record.get("is_deleted"))
- row["source_file"] = row.get("source_file")
- row["fetched_at"] = row.get("fetched_at")
-
- if "ods_assistant_account" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["assistant_name"] = record.get("assistantName") or record.get("name")
- row["mobile"] = record.get("mobile")
- row["assistant_no"] = record.get("assistant_no") or record.get("assistantNo")
- row["team_id"] = record.get("teamId")
- row["team_name"] = record.get("teamName")
- row["group_id"] = record.get("group_id")
- row["group_name"] = record.get("group_name")
- row["job_num"] = record.get("job_num")
- row["entry_type"] = record.get("entry_type")
- row["leave_status"] = record.get("leave_status")
- row["assistant_status"] = record.get("assistant_status")
- row["allow_cx"] = to_bool(record.get("allow_cx"))
- row["status"] = record.get("status")
- row["hired_date"] = record.get("hireDate")
- row["left_date"] = record.get("leaveDate")
-
- if "ods_assistant_service_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["assistant_id"] = record.get("assistantId") or record.get("site_assistant_id")
- row["assistant_name"] = record.get("assistantName") or record.get("ledger_name")
- row["service_type"] = record.get("serviceType") or record.get("order_assistant_type")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["start_time"] = record.get("start_use_time") or record.get("startTime") or record.get("ledger_start_time")
- row["end_time"] = record.get("end_time") or record.get("last_use_time") or record.get("ledger_end_time")
- row["duration_seconds"] = record.get("real_use_seconds") or record.get("duration")
- row["original_fee"] = record.get("originFee") or record.get("original_fee") or record.get("ledger_amount")
- row["member_discount_amount"] = record.get("member_discount_amount")
- row["manual_discount_amount"] = record.get("manual_discount_amount")
- row["coupon_discount_amount"] = record.get("coupon_deduct_money")
- row["final_fee"] = record.get("finalFee") or record.get("final_fee") or record.get("service_money")
- row["member_id"] = record.get("memberId") or record.get("tenant_member_id")
- row["operator_id"] = record.get("operator_id")
- row["salesman_id"] = record.get("salesman_user_id")
- row["is_canceled"] = bool(record.get("is_trash"))
- row["cancel_time"] = record.get("trash_time")
- row["skill_grade"] = record.get("skill_grade")
- row["service_grade"] = record.get("service_grade")
- row["composite_grade"] = record.get("composite_grade")
- row["overall_score"] = record.get("sum_grade")
- row["status"] = record.get("status")
-
- if "ods_assistant_cancel_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["ledger_id"] = record.get("ledgerId")
- row["assistant_id"] = record.get("assistantId")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["table_id"] = record.get("tableId")
- row["table_area_id"] = record.get("tableAreaId")
- row["table_area_name"] = record.get("tableArea")
- row["table_name"] = record.get("tableName")
- row["assistant_on"] = record.get("assistantOn")
- row["pd_charge_minutes"] = record.get("pdChargeMinutes")
- row["assistant_abolish_amount"] = record.get("assistantAbolishAmount")
- row["reason"] = record.get("reason")
- row["cancel_time"] = record.get("cancel_time") or record.get("cancelTime")
- row["operator_id"] = record.get("operatorId")
- row["operator_name"] = record.get("operatorName")
-
- if "ods_table_info" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["table_code"] = record.get("tableCode")
- row["table_name"] = record.get("tableName")
- row["table_type"] = record.get("tableType")
- row["area_name"] = record.get("areaName")
- row["site_table_area_id"] = record.get("site_table_area_id") or record.get("siteTableAreaId")
- row["tenant_table_area_id"] = record.get("tenant_table_area_id") or record.get("tenantTableAreaId")
- row["table_price"] = record.get("table_price") or record.get("tablePrice")
- row["table_status"] = record.get("table_status") or record.get("tableStatusName") or record.get("table_status")
- row["audit_status"] = record.get("audit_status")
- row["show_status"] = record.get("show_status")
- row["light_status"] = record.get("light_status")
- row["virtual_table"] = to_bool(record.get("virtual_table"))
- row["is_rest_area"] = to_bool(record.get("is_rest_area"))
- row["charge_free"] = to_bool(record.get("charge_free"))
- row["table_cloth_use_time"] = record.get("table_cloth_use_time")
- row["table_cloth_use_cycle"] = record.get("table_cloth_use_Cycle")
- row["status"] = record.get("status")
- row["created_time"] = record.get("createTime")
- row["updated_time"] = record.get("updateTime")
-
- if "ods_table_use_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["table_id"] = record.get("tableId") or record.get("site_table_id")
- row["table_name"] = record.get("tableName") or record.get("ledger_name")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["start_time"] = record.get("start_use_time") or record.get("startTime") or record.get("ledger_start_time")
- row["end_time"] = record.get("end_time") or record.get("ledger_end_time")
- row["duration_seconds"] = record.get("real_table_use_seconds") or record.get("duration")
- row["billing_unit_price"] = record.get("ledger_unit_price")
- row["billing_count"] = record.get("ledger_count")
- row["original_table_fee"] = record.get("originFee") or record.get("original_table_fee") or record.get("ledger_amount")
- row["member_discount_amount"] = record.get("member_discount_amount")
- row["coupon_discount_amount"] = record.get("coupon_promotion_amount")
- row["manual_discount_amount"] = record.get("adjust_amount") or record.get("discountAmount")
- row["service_fee"] = record.get("mgmt_fee") or record.get("service_money")
- row["final_table_fee"] = (
- record.get("finalFee")
- or record.get("final_table_fee")
- or record.get("real_table_charge_money")
- )
- row["member_id"] = record.get("memberId")
- row["operator_id"] = record.get("operator_id")
- row["salesman_id"] = record.get("salesman_user_id")
- row["is_canceled"] = bool(record.get("is_delete"))
- row["cancel_time"] = record.get("cancel_time")
- row["site_table_area_id"] = record.get("site_table_area_id")
- row["tenant_table_area_id"] = record.get("tenant_table_area_id")
- row["site_table_area_name"] = record.get("site_table_area_name")
- row["is_single_order"] = to_bool(record.get("is_single_order"))
- row["used_card_amount"] = record.get("used_card_amount")
- row["adjust_amount"] = record.get("adjust_amount")
- row["coupon_promotion_amount"] = record.get("coupon_promotion_amount")
- row["service_money"] = record.get("service_money")
- row["mgmt_fee"] = record.get("mgmt_fee")
- row["fee_total"] = record.get("fee_total")
- row["last_use_time"] = record.get("last_use_time")
- row["ledger_start_time"] = record.get("ledger_start_time")
- row["ledger_end_time"] = record.get("ledger_end_time")
- row["ledger_status"] = record.get("ledger_status")
- row["start_use_time"] = record.get("start_use_time")
- row["add_clock_seconds"] = record.get("add_clock_seconds")
- row["status"] = record.get("status")
-
- if "ods_table_fee_adjust" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["ledger_id"] = record.get("ledgerId")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["discount_amount"] = record.get("discountAmount")
- row["reason"] = record.get("reason")
- row["operator_id"] = record.get("operatorId")
- row["operator_name"] = record.get("operatorName")
- row["created_at"] = record.get("created_at") or record.get("createTime")
-
- if "ods_store_product" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["goods_id"] = record.get("goodsId")
- row["goods_name"] = record.get("goodsName")
- row["category_id"] = record.get("categoryId")
- row["category_name"] = record.get("categoryName")
- row["unit"] = record.get("unit")
- row["sale_price"] = record.get("salePrice")
- row["cost_price"] = record.get("costPrice")
- row["sale_num"] = record.get("sale_num")
- row["stock_a"] = record.get("stock_A")
- row["stock"] = record.get("stock")
- row["provisional_total_cost"] = record.get("provisional_total_cost")
- row["total_purchase_cost"] = record.get("total_purchase_cost")
- row["batch_stock_quantity"] = record.get("batch_stock_quantity")
- row["goods_state"] = record.get("goods_state")
- row["status"] = record.get("status")
-
- if "ods_store_sale_item" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["order_goods_id"] = record.get("order_goods_id") or record.get("orderGoodsId")
- row["site_goods_id"] = record.get("site_goods_id") or record.get("siteGoodsId")
- row["goods_id"] = record.get("tenant_goods_id") or record.get("goodsId")
- row["goods_name"] = record.get("goodsName") or record.get("ledger_name")
- row["category_id"] = record.get("categoryId") or record.get("tenant_goods_category_id")
- row["quantity"] = record.get("quantity") or record.get("ledger_count")
- row["unit_price"] = record.get("unitPrice") or record.get("ledger_unit_price")
- row["original_amount"] = record.get("originalAmount") or record.get("ledger_amount")
- row["discount_amount"] = record.get("discountAmount") or record.get("discount_money")
- row["final_amount"] = record.get("finalAmount") or record.get("real_goods_money")
- row["discount_price"] = record.get("discount_price")
- row["cost_money"] = record.get("cost_money")
- row["coupon_deduct_amount"] = record.get("coupon_deduct_money")
- row["member_discount_amount"] = record.get("member_discount_amount")
- row["point_discount_money"] = record.get("point_discount_money")
- row["point_discount_cost"] = record.get("point_discount_money_cost")
- row["sales_type"] = record.get("sales_type")
- row["goods_remark"] = record.get("goods_remark")
- row["is_gift"] = to_bool(record.get("isGift"))
- row["sale_time"] = record.get("saleTime") or record.get("create_time")
- row["salesman_id"] = record.get("salesman_user_id")
- row["operator_id"] = record.get("operator_id")
- row["is_refunded"] = to_bool(record.get("is_delete")) or bool(record.get("returns_number"))
-
- if "ods_group_package_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["package_id"] = record.get("packageId")
- row["coupon_id"] = record.get("couponId")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["member_id"] = record.get("memberId")
- row["status"] = record.get("status")
- row["used_time"] = record.get("usedTime")
- row["deduct_amount"] = record.get("deductAmount")
- row["settle_price"] = record.get("settlePrice")
- row["coupon_code"] = record.get("coupon_code") or record.get("couponCode")
-
- if "ods_group_package" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["package_name"] = record.get("packageName")
- row["table_area_id"] = record.get("table_area_id") or record.get("tableAreaId")
- row["table_area_name"] = record.get("tableAreaName")
- row["platform_code"] = record.get("platformCode")
- row["status"] = record.get("status")
- row["face_price"] = record.get("facePrice")
- row["settle_price"] = record.get("settlePrice")
- row["selling_price"] = record.get("selling_price")
- row["duration"] = record.get("duration")
- row["valid_from"] = record.get("validFrom") or record.get("start_time")
- row["valid_to"] = record.get("validTo") or record.get("end_time")
- row["start_time"] = record.get("start_time")
- row["end_time"] = record.get("end_time")
- row["is_enabled"] = to_bool(record.get("is_enabled"))
- row["is_delete"] = to_bool(record.get("is_delete"))
- row["package_type"] = record.get("type")
- row["usable_count"] = record.get("usable_count")
- row["creator_name"] = record.get("creator_name")
- row["tenant_table_area_id"] = record.get("tenant_table_area_id")
-
- if "ods_platform_coupon_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["platform_code"] = record.get("platformCode")
- row["verify_code"] = record.get("verifyCode")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["member_id"] = record.get("memberId")
- row["status"] = record.get("status")
- row["used_time"] = record.get("usedTime")
- row["deduct_amount"] = record.get("deductAmount")
- row["settle_price"] = record.get("settlePrice")
-
- if "ods_payment_record" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["member_id"] = record.get("memberId")
- row["pay_method_code"] = record.get("payMethodCode") or record.get("pay_type") or record.get("payment_method")
- row["pay_method_name"] = record.get("payMethodName")
- row["pay_status"] = record.get("pay_status")
- row["pay_amount"] = record.get("payAmount")
- row["pay_time"] = record.get("payTime")
- row["online_pay_channel"] = record.get("online_pay_channel")
- row["transaction_id"] = record.get("transaction_id")
- row["operator_id"] = record.get("operator_id")
- row["remark"] = record.get("remark")
- row["relate_type"] = record.get("relateType")
- row["relate_id"] = record.get("relateId")
-
- if "ods_refund_record" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["member_id"] = record.get("memberId")
- row["pay_sn"] = record.get("pay_sn")
- row["pay_amount"] = record.get("pay_amount")
- row["pay_status"] = record.get("pay_status")
- row["is_revoke"] = to_bool(record.get("is_revoke"))
- row["is_delete"] = to_bool(record.get("is_delete"))
- row["online_pay_channel"] = record.get("online_pay_channel")
- row["pay_method_code"] = record.get("payMethodCode")
- row["refund_amount"] = record.get("refundAmount")
- row["refund_time"] = record.get("refundTime")
- row["action_type"] = record.get("action_type")
- row["pay_terminal"] = record.get("pay_terminal")
- row["pay_config_id"] = record.get("pay_config_id")
- row["cashier_point_id"] = record.get("cashier_point_id")
- row["operator_id"] = record.get("operator_id")
- row["member_card_id"] = record.get("member_card_id")
- row["balance_frozen_amount"] = record.get("balance_frozen_amount")
- row["card_frozen_amount"] = record.get("card_frozen_amount")
- row["round_amount"] = record.get("round_amount")
- row["online_pay_type"] = record.get("online_pay_type")
- row["channel_payer_id"] = record.get("channel_payer_id")
- row["channel_pay_no"] = record.get("channel_pay_no")
- row["check_status"] = record.get("check_status")
- row["channel_fee"] = record.get("channel_fee")
- row["relate_type"] = record.get("relate_type")
- row["relate_id"] = record.get("relate_id")
- row["status"] = record.get("status")
- row["reason"] = record.get("reason")
- row["related_payment_id"] = record.get("related_payment_id") or record.get("payment_id")
-
- if "ods_inventory_change" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["site_goods_id"] = record.get("siteGoodsId")
- row["goods_id"] = record.get("goodsId")
- row["stock_type"] = record.get("stockType")
- row["change_amount"] = record.get("changeAmount") or record.get("changeNum")
- row["before_stock"] = record.get("beforeStock") or record.get("startNum")
- row["after_stock"] = record.get("afterStock") or record.get("endNum")
- row["change_amount_alt"] = record.get("changeNumA")
- row["before_stock_alt"] = record.get("startNumA")
- row["after_stock_alt"] = record.get("endNumA")
- row["change_type"] = record.get("changeType")
- row["relate_id"] = record.get("relateId")
- row["unit"] = record.get("unit")
- row["price"] = record.get("price")
- row["goods_category_id"] = record.get("goodsCategoryId")
- row["goods_second_category_id"] = record.get("goodsSecondCategoryId")
- row["remark"] = record.get("remark")
- row["operator_id"] = record.get("operatorId")
- row["operator_name"] = record.get("operatorName")
- row["change_time"] = record.get("changeTime") or record.get("createTime")
-
- if "ods_inventory_stock" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["goods_id"] = record.get("goodsId")
- row["goods_name"] = record.get("goodsName")
- row["goods_unit"] = record.get("goodsUnit")
- row["goods_category_id"] = record.get("goodsCategoryId")
- row["goods_second_category_id"] = record.get("goodsCategorySecondId")
- row["range_start_stock"] = record.get("rangeStartStock")
- row["range_end_stock"] = record.get("rangeEndStock")
- row["range_in"] = record.get("rangeIn")
- row["range_out"] = record.get("rangeOut")
- row["range_inventory"] = record.get("rangeInventory")
- row["range_sale"] = record.get("rangeSale")
- row["range_sale_money"] = record.get("rangeSaleMoney")
- row["current_stock"] = record.get("currentStock")
- row["cost_price"] = record.get("costPrice")
- row["category_name"] = record.get("categoryName")
-
- if "ods_goods_category" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["category_name"] = record.get("categoryName")
- row["parent_id"] = record.get("parentId")
- row["level_no"] = record.get("levelNo")
- row["status"] = record.get("status")
- row["remark"] = record.get("remark")
-
- if "ods_order_receipt_detail" in table:
- detail = record
- if isinstance(record.get("data"), dict):
- detail = record["data"].get("data", record["data"])
- row["tenant_id"] = pick(detail, "tenantId", "tenant_id")
- row["order_trade_no"] = detail.get("orderTradeNo")
- row["order_settle_number"] = detail.get("orderSettleNumber")
- row["settle_type"] = to_int(detail.get("settleType"))
- row["receipt_no"] = detail.get("receiptNo")
- row["receipt_time"] = detail.get("receiptTime")
- row["total_amount"] = detail.get("totalAmount") or detail.get("ledgerAmount")
- row["discount_amount"] = detail.get("discountAmount")
- row["final_amount"] = detail.get("finalAmount")
- row["actual_payment"] = detail.get("actualPayment")
- row["ledger_amount"] = detail.get("ledgerAmount")
- row["member_offer_amount"] = detail.get("memberOfferAmount")
- row["delivery_fee"] = detail.get("deliveryFee")
- row["adjust_amount"] = detail.get("adjustAmount")
- row["payment_method"] = detail.get("paymentMethod")
- row["pay_time"] = detail.get("payTime")
- row["member_id"] = detail.get("memberId")
- row["order_remark"] = detail.get("orderRemark")
- row["cashier_name"] = detail.get("cashierName")
- row["ticket_remark"] = detail.get("ticketRemark")
- row["ticket_custom_content"] = detail.get("ticketCustomContent")
- row["voucher_money"] = detail.get("voucherMoney")
- row["reward_name"] = detail.get("rewardName")
- row["consume_money"] = detail.get("consumeMoney")
- row["refund_amount"] = detail.get("refundAmount")
- row["balance_amount"] = detail.get("balanceAmount")
- row["coupon_amount"] = detail.get("couponAmount")
- row["member_deduct_amount"] = detail.get("memberDeductAmount")
- row["prepay_money"] = detail.get("prepayMoney")
- row["delivery_address"] = detail.get("deliveryAddress")
- row["snapshot_raw"] = detail.get("siteProfile") or record.get("site_profile")
- row["member_snapshot"] = detail.get("memberProfile")
- if isinstance(row.get("snapshot_raw"), (dict, list)):
- row["snapshot_raw"] = json.dumps(row["snapshot_raw"], ensure_ascii=False)
- if isinstance(row.get("member_snapshot"), (dict, list)):
- row["member_snapshot"] = json.dumps(row["member_snapshot"], ensure_ascii=False)
-
- if "ods_order_settle" in table:
- settle_node = record.get("settleList") or record.get("settle")
- if not settle_node and isinstance(record.get("data"), dict):
- settle_node = record["data"].get("settleList") or record["data"].get("settle")
- if isinstance(settle_node, list):
- settle = settle_node[0] if settle_node else {}
- else:
- settle = settle_node or record
- if isinstance(settle, dict):
- row["site_id"] = row.get("site_id") or settle.get("siteId")
- row["tenant_id"] = pick(settle, "tenantId", "tenant_id")
- row["settle_relate_id"] = settle.get("settleRelateId")
- row["settle_name"] = settle.get("settleName")
- row["settle_type"] = settle.get("settleType")
- row["settle_status"] = settle.get("settleStatus")
- row["member_id"] = settle.get("memberId")
- row["member_name"] = settle.get("memberName")
- row["member_phone"] = settle.get("memberPhone")
- row["table_id"] = settle.get("tableId")
- row["consume_money"] = settle.get("consumeMoney")
- row["table_charge_money"] = settle.get("tableChargeMoney")
- row["goods_money"] = settle.get("goodsMoney")
- row["service_money"] = settle.get("serviceMoney")
- row["assistant_pd_money"] = settle.get("assistantPdMoney")
- row["assistant_cx_money"] = settle.get("assistantCxMoney")
- row["pay_amount"] = settle.get("payAmount")
- row["cash_amount"] = settle.get("cashAmount")
- row["online_amount"] = settle.get("onlineAmount")
- row["point_amount"] = settle.get("pointAmount")
- row["coupon_amount"] = settle.get("couponAmount")
- row["card_amount"] = settle.get("cardAmount")
- row["balance_amount"] = settle.get("balanceAmount")
- row["refund_amount"] = settle.get("refundAmount")
- row["prepay_money"] = settle.get("prepayMoney")
- row["adjust_amount"] = settle.get("adjustAmount")
- row["rounding_amount"] = settle.get("roundingAmount")
- row["member_discount_amount"] = settle.get("memberDiscountAmount")
- row["coupon_sale_amount"] = settle.get("couponSaleAmount")
- row["goods_promotion_money"] = settle.get("goodsPromotionMoney")
- row["assistant_promotion_money"] = settle.get("assistantPromotionMoney")
- row["point_discount_price"] = settle.get("pointDiscountPrice")
- row["point_discount_cost"] = settle.get("pointDiscountCost")
- row["real_goods_money"] = settle.get("realGoodsMoney")
- row["assistant_manual_discount"] = settle.get("assistantManualDiscount")
- row["all_coupon_discount"] = settle.get("allCouponDiscount")
- row["is_use_coupon"] = to_bool(settle.get("isUseCoupon"))
- row["is_use_discount"] = to_bool(settle.get("isUseDiscount"))
- row["is_activity"] = to_bool(settle.get("isActivity"))
- row["is_bind_member"] = to_bool(settle.get("isBindMember"))
- row["is_first"] = to_bool(settle.get("isFirst"))
- row["recharge_card_amount"] = settle.get("rechargeCardAmount")
- row["gift_card_amount"] = settle.get("giftCardAmount")
- row["payment_method"] = settle.get("paymentMethod")
- row["create_time"] = settle.get("createTime")
- row["pay_time"] = settle.get("payTime")
- row["revoke_order_id"] = settle.get("revokeOrderId")
- row["revoke_order_name"] = settle.get("revokeOrderName")
- row["revoke_time"] = settle.get("revokeTime")
- row["can_be_revoked"] = settle.get("canBeRevoked")
- row["serial_number"] = settle.get("serialNumber")
- row["sales_man_name"] = settle.get("salesManName")
- row["sales_man_user_id"] = settle.get("salesManUserId")
- row["order_remark"] = settle.get("orderRemark")
- row["operator_id"] = settle.get("operatorId")
- row["operator_name"] = settle.get("operatorName")
-
- if "ods_product" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["goods_id"] = record.get("goodsId")
- row["goods_name"] = record.get("goodsName")
- row["goods_code"] = record.get("goodsCode")
- row["category_id"] = record.get("categoryId")
- row["category_name"] = record.get("categoryName")
- row["goods_second_category_id"] = record.get("goods_second_category_id") or record.get("goodsSecondCategoryId")
- row["unit"] = record.get("unit")
- row["price"] = record.get("price")
- row["cost_price"] = record.get("cost_price")
- row["market_price"] = record.get("market_price")
- row["goods_state"] = record.get("goods_state")
- row["goods_cover"] = record.get("goods_cover")
- row["goods_bar_code"] = record.get("goods_bar_code")
- row["able_discount"] = record.get("able_discount")
- row["is_delete"] = record.get("is_delete")
- row["status"] = record.get("status")
-
- if "ods_platform_coupon_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
- row["platform_code"] = record.get("platformCode")
- row["verify_code"] = record.get("verifyCode")
- row["coupon_code"] = record.get("coupon_code")
- row["coupon_channel"] = record.get("coupon_channel")
- row["order_trade_no"] = record.get("orderTradeNo")
- row["order_settle_id"] = record.get("orderSettleId")
- row["member_id"] = record.get("memberId")
- row["status"] = record.get("use_status") or record.get("status")
- row["used_time"] = record.get("consume_time") or record.get("usedTime")
- row["deduct_amount"] = record.get("deductAmount")
- row["settle_price"] = record.get("sale_price") or record.get("settlePrice")
- row["coupon_money"] = record.get("coupon_money")
-
- if "ods_table_use_log" in table:
- row["tenant_id"] = pick(record, "tenantId", "tenant_id")
-
- def _ensure_tuple(self, value):
- if isinstance(value, tuple):
- return value
- return (value,)
-
- def _bulk_insert(self, table: str, rows: list[dict]):
- if not rows:
- return
-
- columns = list(rows[0].keys())
- col_clause = ", ".join(columns)
- val_clause = ", ".join(f"%({col})s" for col in columns)
- conflict_cols = ["site_id"] + self._get_conflict_columns(table)
- conflict_clause = ", ".join(conflict_cols)
-
- sql = f"""
- INSERT INTO {table} ({col_clause})
- VALUES ({val_clause})
- ON CONFLICT ({conflict_clause}) DO UPDATE SET
- payload = EXCLUDED.payload,
- fetched_at = EXCLUDED.fetched_at,
- source_file = EXCLUDED.source_file
- """
- self.db.batch_execute(sql, rows)
+ if dt in ("numeric", "double precision", "real", "decimal"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return float(value)
+ except Exception:
+ return None
+ if dt.startswith("timestamp") or dt in ("date", "time", "interval"):
+ return value if isinstance(value, str) else None
+ return value
diff --git a/etl_billiards/tasks/members_dwd_task.py b/etl_billiards/tasks/members_dwd_task.py
index c191b80..0658c2a 100644
--- a/etl_billiards/tasks/members_dwd_task.py
+++ b/etl_billiards/tasks/members_dwd_task.py
@@ -1,13 +1,14 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
from .base_dwd_task import BaseDwdTask
from loaders.dimensions.member import MemberLoader
from models.parsers import TypeParser
import json
+from utils.windowing import build_window_segments
class MembersDwdTask(BaseDwdTask):
"""
DWD Task: Process Member Records from ODS to Dimension Table
- Source: billiards_ods.ods_member_profile
+ Source: billiards_ods.member_profiles
Target: billiards.dim_member
"""
@@ -17,53 +18,72 @@ class MembersDwdTask(BaseDwdTask):
def execute(self) -> dict:
self.logger.info(f"Starting {self.get_task_code()} task")
- window_start, window_end, _ = self._get_time_window()
- self.logger.info(f"Processing window: {window_start} to {window_end}")
+ base_start, base_end, _ = self._get_time_window()
+ segments = build_window_segments(
+ self.config,
+ base_start,
+ base_end,
+ tz=self.tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(base_start, base_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info(f"{self.get_task_code()}: ????? {total_segments} ?")
loader = MemberLoader(self.db)
store_id = self.config.get("app.store_id")
total_inserted = 0
total_updated = 0
- total_errors = 0
- # Iterate ODS Data
- batches = self.iter_ods_rows(
- table_name="billiards_ods.ods_member_profile",
- columns=["site_id", "member_id", "payload", "fetched_at"],
- start_time=window_start,
- end_time=window_end
+ for idx, (window_start, window_end) in enumerate(segments, start=1):
+ self.logger.info(
+ f"Processing window {idx}/{total_segments}: {window_start} to {window_end}"
+ )
+ batches = self.iter_ods_rows(
+ table_name="billiards_ods.member_profiles",
+ columns=["site_id", "member_id", "payload", "fetched_at"],
+ start_time=window_start,
+ end_time=window_end
+ )
+
+ for batch in batches:
+ if not batch:
+ continue
+
+ parsed_rows = []
+ for row in batch:
+ payload = self.parse_payload(row)
+ if not payload:
+ continue
+
+ parsed = self._parse_member(payload, store_id)
+ if parsed:
+ parsed_rows.append(parsed)
+
+ if parsed_rows:
+ inserted, updated, skipped = loader.upsert_members(parsed_rows, store_id)
+ total_inserted += inserted
+ total_updated += updated
+
+ self.db.commit()
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+
+ self.logger.info(
+ f"Task {self.get_task_code()} completed. Inserted: {total_inserted}, Updated: {total_updated}"
)
- for batch in batches:
- if not batch:
- continue
-
- parsed_rows = []
- for row in batch:
- payload = self.parse_payload(row)
- if not payload:
- continue
-
- parsed = self._parse_member(payload, store_id)
- if parsed:
- parsed_rows.append(parsed)
-
- if parsed_rows:
- inserted, updated, skipped = loader.upsert_members(parsed_rows, store_id)
- total_inserted += inserted
- total_updated += updated
-
- self.db.commit()
-
- self.logger.info(f"Task {self.get_task_code()} completed. Inserted: {total_inserted}, Updated: {total_updated}")
-
return {
"status": "success",
"inserted": total_inserted,
"updated": total_updated,
- "window_start": window_start.isoformat(),
- "window_end": window_end.isoformat()
+ "window_start": overall_start.isoformat(),
+ "window_end": overall_end.isoformat()
}
def _parse_member(self, raw: dict, store_id: int) -> dict:
@@ -87,3 +107,4 @@ class MembersDwdTask(BaseDwdTask):
except Exception as e:
self.logger.warning(f"Error parsing member: {e}")
return None
+
diff --git a/etl_billiards/tasks/ods_json_archive_task.py b/etl_billiards/tasks/ods_json_archive_task.py
new file mode 100644
index 0000000..df490cf
--- /dev/null
+++ b/etl_billiards/tasks/ods_json_archive_task.py
@@ -0,0 +1,260 @@
+# -*- coding: utf-8 -*-
+"""在线抓取 ODS 相关接口并落盘为 JSON(用于后续离线回放/入库)。"""
+
+from __future__ import annotations
+
+from dataclasses import dataclass
+from pathlib import Path
+
+from api.client import APIClient
+from models.parsers import TypeParser
+from utils.json_store import dump_json, endpoint_to_filename
+
+from .base_task import BaseTask, TaskContext
+
+
+@dataclass(frozen=True)
+class EndpointSpec:
+ endpoint: str
+ window_style: str # site | start_end | range | pay | none
+ data_path: tuple[str, ...] = ("data",)
+ list_key: str | None = None
+
+
+class OdsJsonArchiveTask(BaseTask):
+ """
+ 抓取一组 ODS 所需接口并落盘为“简化 JSON”:
+ {"code": 0, "data": [...records...]}
+
+ 说明:
+ - 该输出格式与 tasks/manual_ingest_task.py 的解析逻辑兼容;
+ - 默认每页一个文件,避免单文件过大;
+ - 结算小票(/Order/GetOrderSettleTicketNew)按 orderSettleId 分文件写入。
+ """
+
+ ENDPOINTS: tuple[EndpointSpec, ...] = (
+ EndpointSpec("/MemberProfile/GetTenantMemberList", "site", list_key="tenantMemberInfos"),
+ EndpointSpec("/MemberProfile/GetTenantMemberCardList", "site", list_key="tenantMemberCards"),
+ EndpointSpec("/MemberProfile/GetMemberCardBalanceChange", "start_end"),
+ EndpointSpec("/PersonnelManagement/SearchAssistantInfo", "site", list_key="assistantInfos"),
+ EndpointSpec(
+ "/AssistantPerformance/GetOrderAssistantDetails",
+ "start_end",
+ list_key="orderAssistantDetails",
+ ),
+ EndpointSpec(
+ "/AssistantPerformance/GetAbolitionAssistant",
+ "start_end",
+ list_key="abolitionAssistants",
+ ),
+ EndpointSpec("/Table/GetSiteTables", "site", list_key="siteTables"),
+ EndpointSpec(
+ "/TenantGoodsCategory/QueryPrimarySecondaryCategory",
+ "site",
+ list_key="goodsCategoryList",
+ ),
+ EndpointSpec("/TenantGoods/QueryTenantGoods", "site", list_key="tenantGoodsList"),
+ EndpointSpec("/TenantGoods/GetGoodsInventoryList", "site", list_key="orderGoodsList"),
+ EndpointSpec("/TenantGoods/GetGoodsStockReport", "site"),
+ EndpointSpec("/TenantGoods/GetGoodsSalesList", "start_end", list_key="orderGoodsLedgers"),
+ EndpointSpec(
+ "/PackageCoupon/QueryPackageCouponList",
+ "site",
+ list_key="packageCouponList",
+ ),
+ EndpointSpec("/Site/GetSiteTableUseDetails", "start_end", list_key="siteTableUseDetailsList"),
+ EndpointSpec("/Site/GetSiteTableOrderDetails", "start_end", list_key="siteTableUseDetailsList"),
+ EndpointSpec("/Site/GetTaiFeeAdjustList", "start_end", list_key="taiFeeAdjustInfos"),
+ EndpointSpec(
+ "/GoodsStockManage/QueryGoodsOutboundReceipt",
+ "start_end",
+ list_key="queryDeliveryRecordsList",
+ ),
+ EndpointSpec("/Promotion/GetOfflineCouponConsumePageList", "start_end"),
+ EndpointSpec("/Order/GetRefundPayLogList", "start_end"),
+ EndpointSpec("/Site/GetAllOrderSettleList", "range", list_key="settleList"),
+ EndpointSpec("/Site/GetRechargeSettleList", "range", list_key="settleList"),
+ EndpointSpec("/PayLog/GetPayLogListPage", "pay"),
+ )
+
+ TICKET_ENDPOINT = "/Order/GetOrderSettleTicketNew"
+
+ def get_task_code(self) -> str:
+ return "ODS_JSON_ARCHIVE"
+
+ def extract(self, context: TaskContext) -> dict:
+ base_client = getattr(self.api, "base", None) or self.api
+ if not isinstance(base_client, APIClient):
+ raise TypeError("ODS_JSON_ARCHIVE 需要 APIClient(在线抓取)")
+
+ output_dir = getattr(self.api, "output_dir", None)
+ if output_dir:
+ out = Path(output_dir)
+ else:
+ out = Path(self.config.get("pipeline.fetch_root") or self.config["pipeline"]["fetch_root"])
+ out.mkdir(parents=True, exist_ok=True)
+
+ write_pretty = bool(self.config.get("io.write_pretty_json", False))
+ page_size = int(self.config.get("api.page_size", 200) or 200)
+ store_id = int(context.store_id)
+
+ total_records = 0
+ ticket_ids: set[int] = set()
+ per_endpoint: list[dict] = []
+
+ self.logger.info(
+ "ODS_JSON_ARCHIVE: 开始抓取,窗口[%s ~ %s] 输出目录=%s",
+ context.window_start,
+ context.window_end,
+ out,
+ )
+
+ for spec in self.ENDPOINTS:
+ self.logger.info("ODS_JSON_ARCHIVE: 抓取 endpoint=%s", spec.endpoint)
+ built_params = self._build_params(
+ spec.window_style, store_id, context.window_start, context.window_end
+ )
+ # /TenantGoods/GetGoodsInventoryList 要求 siteId 为数组(标量会触发服务端异常,返回畸形状态行 HTTP/1.1 1400)
+ if spec.endpoint == "/TenantGoods/GetGoodsInventoryList":
+ built_params["siteId"] = [store_id]
+ params = self._merge_common_params(built_params)
+
+ base_filename = endpoint_to_filename(spec.endpoint)
+ stem = Path(base_filename).stem
+ suffix = Path(base_filename).suffix or ".json"
+
+ endpoint_records = 0
+ endpoint_pages = 0
+ endpoint_error: str | None = None
+
+ try:
+ for page_no, records, _, _ in base_client.iter_paginated(
+ endpoint=spec.endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=spec.data_path,
+ list_key=spec.list_key,
+ ):
+ endpoint_pages += 1
+ total_records += len(records)
+ endpoint_records += len(records)
+
+ if spec.endpoint == "/PayLog/GetPayLogListPage":
+ for rec in records or []:
+ relate_id = TypeParser.parse_int(
+ (rec or {}).get("relateId")
+ or (rec or {}).get("orderSettleId")
+ or (rec or {}).get("order_settle_id")
+ )
+ if relate_id:
+ ticket_ids.add(relate_id)
+
+ out_path = out / f"{stem}__p{int(page_no):04d}{suffix}"
+ dump_json(out_path, {"code": 0, "data": records}, pretty=write_pretty)
+ except Exception as exc: # noqa: BLE001
+ endpoint_error = f"{type(exc).__name__}: {exc}"
+ self.logger.error("ODS_JSON_ARCHIVE: 接口抓取失败 endpoint=%s err=%s", spec.endpoint, endpoint_error)
+
+ per_endpoint.append(
+ {
+ "endpoint": spec.endpoint,
+ "file_stem": stem,
+ "pages": endpoint_pages,
+ "records": endpoint_records,
+ "error": endpoint_error,
+ }
+ )
+ if endpoint_error:
+ self.logger.warning(
+ "ODS_JSON_ARCHIVE: endpoint=%s 完成(失败)pages=%s records=%s err=%s",
+ spec.endpoint,
+ endpoint_pages,
+ endpoint_records,
+ endpoint_error,
+ )
+ else:
+ self.logger.info(
+ "ODS_JSON_ARCHIVE: endpoint=%s 完成 pages=%s records=%s",
+ spec.endpoint,
+ endpoint_pages,
+ endpoint_records,
+ )
+
+ # Ticket details: per orderSettleId
+ ticket_ids_sorted = sorted(ticket_ids)
+ self.logger.info("ODS_JSON_ARCHIVE: 小票候选数=%s", len(ticket_ids_sorted))
+
+ ticket_file_stem = Path(endpoint_to_filename(self.TICKET_ENDPOINT)).stem
+ ticket_file_suffix = Path(endpoint_to_filename(self.TICKET_ENDPOINT)).suffix or ".json"
+ ticket_records = 0
+
+ for order_settle_id in ticket_ids_sorted:
+ params = self._merge_common_params({"orderSettleId": int(order_settle_id)})
+ try:
+ records, _ = base_client.get_paginated(
+ endpoint=self.TICKET_ENDPOINT,
+ params=params,
+ page_size=None,
+ data_path=("data",),
+ list_key=None,
+ )
+ if not records:
+ continue
+ ticket_records += len(records)
+ out_path = out / f"{ticket_file_stem}__{int(order_settle_id)}{ticket_file_suffix}"
+ dump_json(out_path, {"code": 0, "data": records}, pretty=write_pretty)
+ except Exception as exc: # noqa: BLE001
+ self.logger.error(
+ "ODS_JSON_ARCHIVE: 小票抓取失败 orderSettleId=%s err=%s",
+ order_settle_id,
+ exc,
+ )
+ continue
+
+ total_records += ticket_records
+
+ manifest = {
+ "task": self.get_task_code(),
+ "store_id": store_id,
+ "window_start": context.window_start.isoformat(),
+ "window_end": context.window_end.isoformat(),
+ "page_size": page_size,
+ "total_records": total_records,
+ "ticket_ids": len(ticket_ids_sorted),
+ "ticket_records": ticket_records,
+ "endpoints": per_endpoint,
+ }
+ manifest_path = out / "manifest.json"
+ dump_json(manifest_path, manifest, pretty=True)
+ if hasattr(self.api, "last_dump"):
+ try:
+ self.api.last_dump = {"file": str(manifest_path), "records": total_records, "pages": None}
+ except Exception:
+ pass
+
+ self.logger.info("ODS_JSON_ARCHIVE: 抓取完成,总记录数=%s(含小票=%s)", total_records, ticket_records)
+ return {"fetched": total_records, "ticket_ids": len(ticket_ids_sorted)}
+
+ def _build_params(self, window_style: str, store_id: int, window_start, window_end) -> dict:
+ if window_style == "none":
+ return {}
+ if window_style == "site":
+ return {"siteId": store_id}
+ if window_style == "range":
+ return {
+ "siteId": store_id,
+ "rangeStartTime": TypeParser.format_timestamp(window_start, self.tz),
+ "rangeEndTime": TypeParser.format_timestamp(window_end, self.tz),
+ }
+ if window_style == "pay":
+ return {
+ "siteId": store_id,
+ "StartPayTime": TypeParser.format_timestamp(window_start, self.tz),
+ "EndPayTime": TypeParser.format_timestamp(window_end, self.tz),
+ }
+ # default: startTime/endTime
+ return {
+ "siteId": store_id,
+ "startTime": TypeParser.format_timestamp(window_start, self.tz),
+ "endTime": TypeParser.format_timestamp(window_end, self.tz),
+ }
diff --git a/etl_billiards/tasks/ods_tasks.py b/etl_billiards/tasks/ods_tasks.py
index fce222f..37df0ff 100644
--- a/etl_billiards/tasks/ods_tasks.py
+++ b/etl_billiards/tasks/ods_tasks.py
@@ -1,14 +1,17 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""ODS ingestion tasks."""
from __future__ import annotations
+import json
from dataclasses import dataclass, field
-from datetime import datetime
+from datetime import datetime, timedelta
from typing import Any, Callable, Dict, Iterable, List, Sequence, Tuple, Type
-from loaders.ods import GenericODSLoader
+from psycopg2.extras import Json, execute_values
+
from models.parsers import TypeParser
from .base_task import BaseTask
+from utils.windowing import build_window_segments, calc_window_minutes
ColumnTransform = Callable[[Any], Any]
@@ -60,83 +63,180 @@ class BaseOdsTask(BaseTask):
def get_task_code(self) -> str:
return self.SPEC.code
- def execute(self) -> dict:
+ def execute(self, cursor_data: dict | None = None) -> dict:
spec = self.SPEC
- self.logger.info("开始执行 %s (ODS)", spec.code)
+ self.logger.info("开始执行%s (ODS)", spec.code)
+
+ window_start, window_end, window_minutes = self._resolve_window(cursor_data)
+ segments = build_window_segments(
+ self.config,
+ window_start,
+ window_end,
+ tz=self.tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(window_start, window_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info("%s: 窗口拆分为 %s 段", spec.code, total_segments)
store_id = TypeParser.parse_int(self.config.get("app.store_id"))
if not store_id:
raise ValueError("app.store_id 未配置,无法执行 ODS 任务")
page_size = self.config.get("api.page_size", 200)
- params = self._build_params(spec, store_id)
- columns = self._resolve_columns(spec)
- if spec.conflict_columns_override:
- conflict_columns = list(spec.conflict_columns_override)
- else:
- conflict_columns = []
- if spec.include_site_column:
- conflict_columns.append("site_id")
- conflict_columns += [col.column for col in spec.pk_columns]
- loader = GenericODSLoader(
- self.db,
- spec.table_name,
- columns,
- conflict_columns,
- )
- counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+ total_counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+ segment_results: list[dict] = []
+ params_list: list[dict] = []
source_file = self._resolve_source_file_hint(spec)
try:
- global_index = 0
- for page_no, page_records, _, _ in self.api.iter_paginated(
- endpoint=spec.endpoint,
- params=params,
- page_size=page_size,
- data_path=spec.data_path,
- list_key=spec.list_key,
- ):
- rows: List[dict] = []
- for raw in page_records:
- row = self._build_row(
- spec=spec,
- store_id=store_id,
- record=raw,
- page_no=page_no if spec.include_page_no else None,
- page_size_value=len(page_records)
- if spec.include_page_size
- else None,
+ for idx, (seg_start, seg_end) in enumerate(segments, start=1):
+ params = self._build_params(
+ spec,
+ store_id,
+ window_start=seg_start,
+ window_end=seg_end,
+ )
+ params_list.append(params)
+ segment_counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+
+ self.logger.info(
+ "%s: 开始执行(%s/%s),窗口[%s ~ %s]",
+ spec.code,
+ idx,
+ total_segments,
+ seg_start,
+ seg_end,
+ )
+
+ for _, page_records, _, response_payload in self.api.iter_paginated(
+ endpoint=spec.endpoint,
+ params=params,
+ page_size=page_size,
+ data_path=spec.data_path,
+ list_key=spec.list_key,
+ ):
+ inserted, skipped = self._insert_records_schema_aware(
+ table=spec.table_name,
+ records=page_records,
+ response_payload=response_payload,
source_file=source_file,
- record_index=global_index if spec.include_record_index else None,
+ source_endpoint=spec.endpoint if spec.include_source_endpoint else None,
)
- if row is None:
- counts["skipped"] += 1
- continue
- rows.append(row)
- global_index += 1
+ segment_counts["fetched"] += len(page_records)
+ segment_counts["inserted"] += inserted
+ segment_counts["skipped"] += skipped
- inserted, updated, _ = loader.upsert_rows(rows)
- counts["inserted"] += inserted
- counts["updated"] += updated
- counts["fetched"] += len(page_records)
+ self.db.commit()
+ self._accumulate_counts(total_counts, segment_counts)
+ if total_segments > 1:
+ segment_results.append(
+ {
+ "window": {
+ "start": seg_start,
+ "end": seg_end,
+ "minutes": calc_window_minutes(seg_start, seg_end),
+ },
+ "counts": segment_counts,
+ }
+ )
- self.db.commit()
- self.logger.info("%s ODS 任务完成: %s", spec.code, counts)
- return self._build_result("SUCCESS", counts)
+ self.logger.info("%s ODS 任务完成: %s", spec.code, total_counts)
+ allow_empty_advance = bool(self.config.get("run.allow_empty_result_advance", False))
+ status = "SUCCESS"
+ if total_counts["fetched"] == 0 and not allow_empty_advance:
+ status = "PARTIAL"
+
+ result = self._build_result(status, total_counts)
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+ result["window"] = {
+ "start": overall_start,
+ "end": overall_end,
+ "minutes": calc_window_minutes(overall_start, overall_end),
+ }
+ if total_segments > 1:
+ result["segments"] = segment_results
+ if len(params_list) == 1:
+ result["request_params"] = params_list[0]
+ else:
+ result["request_params"] = params_list
+ return result
except Exception:
self.db.rollback()
- counts["errors"] += 1
+ total_counts["errors"] += 1
self.logger.error("%s ODS 任务失败", spec.code, exc_info=True)
raise
- def _build_params(self, spec: OdsTaskSpec, store_id: int) -> dict:
+ def _resolve_window(self, cursor_data: dict | None) -> tuple[datetime, datetime, int]:
+ base_start, base_end, base_minutes = self._get_time_window(cursor_data)
+
+ if self.config.get("run.force_window_override"):
+ override_start = self.config.get("run.window_override.start")
+ override_end = self.config.get("run.window_override.end")
+ if override_start and override_end:
+ return base_start, base_end, base_minutes
+
+ # 以 ODS 表 MAX(fetched_at) 兜底:避免“窗口游标推进但未实际入库”导致漏数。
+ last_fetched = self._get_max_fetched_at(self.SPEC.table_name)
+ if last_fetched:
+ overlap_seconds = int(self.config.get("run.overlap_seconds", 120) or 120)
+ cursor_end = cursor_data.get("last_end") if isinstance(cursor_data, dict) else None
+ anchor = cursor_end or last_fetched
+ # 如果 cursor_end 比真实入库时间(last_fetched)更靠后,说明游标被推进但表未跟上:改用 last_fetched 作为起点
+ if isinstance(cursor_end, datetime) and cursor_end.tzinfo is None:
+ cursor_end = cursor_end.replace(tzinfo=self.tz)
+ if isinstance(cursor_end, datetime) and cursor_end > last_fetched:
+ anchor = last_fetched
+ start = anchor - timedelta(seconds=max(0, overlap_seconds))
+ if start.tzinfo is None:
+ start = start.replace(tzinfo=self.tz)
+ else:
+ start = start.astimezone(self.tz)
+
+ end = datetime.now(self.tz)
+ minutes = max(1, int((end - start).total_seconds() // 60))
+ return start, end, minutes
+
+ return base_start, base_end, base_minutes
+
+ def _get_max_fetched_at(self, table_name: str) -> datetime | None:
+ try:
+ rows = self.db.query(f"SELECT MAX(fetched_at) AS mx FROM {table_name}")
+ except Exception:
+ return None
+
+ if not rows or not rows[0].get("mx"):
+ return None
+
+ mx = rows[0]["mx"]
+ if not isinstance(mx, datetime):
+ return None
+ if mx.tzinfo is None:
+ return mx.replace(tzinfo=self.tz)
+ return mx.astimezone(self.tz)
+
+ def _build_params(
+ self,
+ spec: OdsTaskSpec,
+ store_id: int,
+ *,
+ window_start: datetime,
+ window_end: datetime,
+ ) -> dict:
base: dict[str, Any] = {}
if spec.include_site_id:
- base["siteId"] = store_id
+ # /TenantGoods/GetGoodsInventoryList 要求 siteId 为数组(标量会触发服务端异常,返回畸形状态行 HTTP/1.1 1400)
+ if spec.endpoint == "/TenantGoods/GetGoodsInventoryList":
+ base["siteId"] = [store_id]
+ else:
+ base["siteId"] = store_id
if spec.requires_window and spec.time_fields:
- window_start, window_end, _ = self._get_time_window()
start_key, end_key = spec.time_fields
base[start_key] = TypeParser.format_timestamp(window_start, self.tz)
base[end_key] = TypeParser.format_timestamp(window_end, self.tz)
@@ -145,109 +245,226 @@ class BaseOdsTask(BaseTask):
params.update(spec.extra_params)
return params
- def _resolve_columns(self, spec: OdsTaskSpec) -> List[str]:
- columns: List[str] = []
- if spec.include_site_column:
- columns.append("site_id")
- seen = set(columns)
- for col_spec in list(spec.pk_columns) + list(spec.extra_columns):
- if col_spec.column not in seen:
- columns.append(col_spec.column)
- seen.add(col_spec.column)
+ # ------------------------------------------------------------------ schema-aware ingest (ODS doc schema)
+ def _get_table_columns(self, table: str) -> list[tuple[str, str, str]]:
+ cache = getattr(self, "_table_columns_cache", {})
+ if table in cache:
+ return cache[table]
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT column_name, data_type, udt_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """
+ with self.db.conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ cols = [(r[0], (r[1] or "").lower(), (r[2] or "").lower()) for r in cur.fetchall()]
+ cache[table] = cols
+ self._table_columns_cache = cache
+ return cols
- if spec.include_record_index and "record_index" not in seen:
- columns.append("record_index")
- seen.add("record_index")
+ def _get_table_pk_columns(self, table: str) -> list[str]:
+ cache = getattr(self, "_table_pk_cache", {})
+ if table in cache:
+ return cache[table]
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT kcu.column_name
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.constraint_name = kcu.constraint_name
+ AND tc.table_schema = kcu.table_schema
+ WHERE tc.constraint_type = 'PRIMARY KEY'
+ AND tc.table_schema = %s
+ AND tc.table_name = %s
+ ORDER BY kcu.ordinal_position
+ """
+ with self.db.conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ cols = [r[0] for r in cur.fetchall()]
+ cache[table] = cols
+ self._table_pk_cache = cache
+ return cols
- if spec.include_page_no and "page_no" not in seen:
- columns.append("page_no")
- seen.add("page_no")
-
- if spec.include_page_size and "page_size" not in seen:
- columns.append("page_size")
- seen.add("page_size")
-
- if spec.include_source_file and "source_file" not in seen:
- columns.append("source_file")
- seen.add("source_file")
-
- if spec.include_source_endpoint and "source_endpoint" not in seen:
- columns.append("source_endpoint")
- seen.add("source_endpoint")
-
- if spec.include_fetched_at and "fetched_at" not in seen:
- columns.append("fetched_at")
- seen.add("fetched_at")
- if "payload" not in seen:
- columns.append("payload")
-
- return columns
-
- def _build_row(
+ def _insert_records_schema_aware(
self,
- spec: OdsTaskSpec,
- store_id: int,
- record: dict,
- page_no: int | None,
- page_size_value: int | None,
+ *,
+ table: str,
+ records: list,
+ response_payload: dict | list | None,
source_file: str | None,
- record_index: int | None = None,
- ) -> dict | None:
- row: dict[str, Any] = {}
- if spec.include_site_column:
- row["site_id"] = store_id
+ source_endpoint: str | None,
+ ) -> tuple[int, int]:
+ """
+ 按 DB 表结构动态写入 ODS(只插新数据:ON CONFLICT DO NOTHING)。
+ 返回 (inserted, skipped)。
+ """
+ if not records:
+ return 0, 0
- for col_spec in spec.pk_columns + spec.extra_columns:
- value = self._extract_value(record, col_spec)
- if value is None and col_spec.required:
- self.logger.warning(
- "%s 缺少必填字段 %s,原始记录: %s",
- spec.code,
- col_spec.column,
- record,
- )
- return None
- row[col_spec.column] = value
+ cols_info = self._get_table_columns(table)
+ if not cols_info:
+ raise ValueError(f"Cannot resolve columns for table={table}")
- if spec.include_page_no:
- row["page_no"] = page_no
- if spec.include_page_size:
- row["page_size"] = page_size_value
- if spec.include_record_index:
- row["record_index"] = record_index
- if spec.include_source_file:
- row["source_file"] = source_file
- if spec.include_source_endpoint:
- row["source_endpoint"] = spec.endpoint
+ pk_cols = self._get_table_pk_columns(table)
+ db_json_cols_lower = {
+ c[0].lower() for c in cols_info if c[1] in ("json", "jsonb") or c[2] in ("json", "jsonb")
+ }
- if spec.include_fetched_at:
- row["fetched_at"] = datetime.now(self.tz)
- row["payload"] = record
- return row
+ col_names = [c[0] for c in cols_info]
+ quoted_cols = ", ".join(f'\"{c}\"' for c in col_names)
+ sql = f"INSERT INTO {table} ({quoted_cols}) VALUES %s"
+ if pk_cols:
+ pk_clause = ", ".join(f'\"{c}\"' for c in pk_cols)
+ sql += f" ON CONFLICT ({pk_clause}) DO NOTHING"
- def _extract_value(self, record: dict, spec: ColumnSpec):
- value = None
- for key in spec.sources:
- value = self._dig(record, key)
- if value is not None:
- break
- if value is None and spec.default is not None:
- value = spec.default
- if value is not None and spec.transform:
- value = spec.transform(value)
+ now = datetime.now(self.tz)
+ json_dump = lambda v: json.dumps(v, ensure_ascii=False) # noqa: E731
+
+ params: list[tuple] = []
+ skipped = 0
+
+ root_site_profile = None
+ if isinstance(response_payload, dict):
+ data_part = response_payload.get("data")
+ if isinstance(data_part, dict):
+ sp = data_part.get("siteProfile") or data_part.get("site_profile")
+ if isinstance(sp, dict):
+ root_site_profile = sp
+
+ for rec in records:
+ if not isinstance(rec, dict):
+ skipped += 1
+ continue
+
+ merged_rec = self._merge_record_layers(rec)
+ if table in {"billiards_ods.recharge_settlements", "billiards_ods.settlement_records"}:
+ site_profile = merged_rec.get("siteProfile") or merged_rec.get("site_profile") or root_site_profile
+ if isinstance(site_profile, dict):
+ # 避免写入 None 覆盖原本存在的 camelCase 字段(例如 tenantId/siteId/siteName)
+ def _fill_missing(target_col: str, candidates: list[Any]):
+ existing = self._get_value_case_insensitive(merged_rec, target_col)
+ if existing not in (None, ""):
+ return
+ for cand in candidates:
+ if cand in (None, "", 0):
+ continue
+ merged_rec[target_col] = cand
+ return
+
+ _fill_missing("tenantid", [site_profile.get("tenant_id"), site_profile.get("tenantId")])
+ _fill_missing("siteid", [site_profile.get("siteId"), site_profile.get("id")])
+ _fill_missing("sitename", [site_profile.get("shop_name"), site_profile.get("siteName")])
+
+ if pk_cols:
+ missing_pk = False
+ for pk in pk_cols:
+ pk_val = self._get_value_case_insensitive(merged_rec, pk)
+ if pk_val is None or pk_val == "":
+ missing_pk = True
+ break
+ if missing_pk:
+ skipped += 1
+ continue
+
+ row_vals: list[Any] = []
+ for (col_name, data_type, _udt) in cols_info:
+ col_lower = col_name.lower()
+ if col_lower == "payload":
+ row_vals.append(Json(rec, dumps=json_dump))
+ continue
+ if col_lower == "source_file":
+ row_vals.append(source_file)
+ continue
+ if col_lower == "source_endpoint":
+ row_vals.append(source_endpoint)
+ continue
+ if col_lower == "fetched_at":
+ row_vals.append(now)
+ continue
+
+ value = self._normalize_scalar(self._get_value_case_insensitive(merged_rec, col_name))
+ if col_lower in db_json_cols_lower:
+ row_vals.append(Json(value, dumps=json_dump) if value is not None else None)
+ continue
+
+ row_vals.append(self._cast_value(value, data_type))
+
+ params.append(tuple(row_vals))
+
+ if not params:
+ return 0, skipped
+
+ inserted = 0
+ chunk_size = int(self.config.get("run.ods_execute_values_page_size", 200) or 200)
+ chunk_size = max(1, min(chunk_size, 2000))
+ with self.db.conn.cursor() as cur:
+ for i in range(0, len(params), chunk_size):
+ chunk = params[i : i + chunk_size]
+ execute_values(cur, sql, chunk, page_size=len(chunk))
+ if cur.rowcount is not None and cur.rowcount > 0:
+ inserted += int(cur.rowcount)
+ return inserted, skipped
+
+ @staticmethod
+ def _merge_record_layers(record: dict) -> dict:
+ merged = record
+ data_part = merged.get("data")
+ while isinstance(data_part, dict):
+ merged = {**data_part, **merged}
+ data_part = data_part.get("data")
+ settle_inner = merged.get("settleList")
+ if isinstance(settle_inner, dict):
+ merged = {**settle_inner, **merged}
+ return merged
+
+ @staticmethod
+ def _get_value_case_insensitive(record: dict | None, col: str | None):
+ if record is None or col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+ @staticmethod
+ def _normalize_scalar(value):
+ if value == "" or value == "{}" or value == "[]":
+ return None
return value
@staticmethod
- def _dig(record: Any, path: str | None):
- if not path:
+ def _cast_value(value, data_type: str):
+ if value is None:
return None
- current = record
- for part in path.split("."):
- if isinstance(current, dict):
- current = current.get(part)
- else:
+ dt = (data_type or "").lower()
+ if dt in ("integer", "bigint", "smallint"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return int(value)
+ except Exception:
return None
- return current
+ if dt in ("numeric", "double precision", "real", "decimal"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return float(value)
+ except Exception:
+ return None
+ if dt.startswith("timestamp") or dt in ("date", "time", "interval"):
+ return value if isinstance(value, (str, datetime)) else None
+ return value
def _resolve_source_file_hint(self, spec: OdsTaskSpec) -> str | None:
resolver = getattr(self.api, "get_source_hint", None)
@@ -265,9 +482,38 @@ def _int_col(name: str, *sources: str, required: bool = False) -> ColumnSpec:
)
+def _decimal_col(name: str, *sources: str) -> ColumnSpec:
+ """??????????????"""
+ return ColumnSpec(
+ column=name,
+ sources=sources,
+ transform=lambda v: TypeParser.parse_decimal(v, 2),
+ )
+
+
+def _bool_col(name: str, *sources: str) -> ColumnSpec:
+ """??????????????0/1?true/false ???"""
+
+ def _to_bool(value):
+ if value is None:
+ return None
+ if isinstance(value, bool):
+ return value
+ s = str(value).strip().lower()
+ if s in {"1", "true", "t", "yes", "y"}:
+ return True
+ if s in {"0", "false", "f", "no", "n"}:
+ return False
+ return bool(value)
+
+ return ColumnSpec(column=name, sources=sources, transform=_to_bool)
+
+
+
+
ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
OdsTaskSpec(
- code="ODS_ASSISTANT_ACCOUNTS",
+ code="ODS_ASSISTANT_ACCOUNT",
class_name="OdsAssistantAccountsTask",
table_name="billiards_ods.assistant_accounts_master",
endpoint="/PersonnelManagement/SearchAssistantInfo",
@@ -281,25 +527,26 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_fetched_at=False,
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
- description="助教账号档案 ODS:SearchAssistantInfo -> assistantInfos 原始 JSON",
+ description="鍔╂暀璐﹀彿妗f ODS锛歋earchAssistantInfo -> assistantInfos 鍘熷 JSON",
),
OdsTaskSpec(
- code="ODS_ORDER_SETTLE",
+ code="ODS_SETTLEMENT_RECORDS",
class_name="OdsOrderSettleTask",
table_name="billiards_ods.settlement_records",
endpoint="/Site/GetAllOrderSettleList",
data_path=("data",),
list_key="settleList",
+ time_fields=("rangeStartTime", "rangeEndTime"),
pk_columns=(),
include_site_column=False,
- include_source_endpoint=False,
+ include_source_endpoint=True,
include_page_no=False,
include_page_size=False,
include_fetched_at=False,
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
- requires_window=False,
- description="结账记录 ODS:GetAllOrderSettleList -> settleList 原始 JSON",
+ requires_window=True,
+ description="缁撹处璁板綍 ODS锛欸etAllOrderSettleList -> settleList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_TABLE_USE",
@@ -317,7 +564,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="台费计费流水 ODS:GetSiteTableOrderDetails -> siteTableUseDetailsList 原始 JSON",
+ description="鍙拌垂璁¤垂娴佹按 ODS锛欸etSiteTableOrderDetails -> siteTableUseDetailsList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_ASSISTANT_LEDGER",
@@ -334,7 +581,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_fetched_at=False,
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
- description="助教服务流水 ODS:GetOrderAssistantDetails -> orderAssistantDetails 原始 JSON",
+ description="鍔╂暀鏈嶅姟娴佹按 ODS锛欸etOrderAssistantDetails -> orderAssistantDetails 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_ASSISTANT_ABOLISH",
@@ -351,10 +598,10 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_fetched_at=False,
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
- description="助教废除记录 ODS:GetAbolitionAssistant -> abolitionAssistants 原始 JSON",
+ description="鍔╂暀搴熼櫎璁板綍 ODS锛欸etAbolitionAssistant -> abolitionAssistants 鍘熷 JSON",
),
OdsTaskSpec(
- code="ODS_GOODS_LEDGER",
+ code="ODS_STORE_GOODS_SALES",
class_name="OdsGoodsLedgerTask",
table_name="billiards_ods.store_goods_sales_records",
endpoint="/TenantGoods/GetGoodsSalesList",
@@ -369,7 +616,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="门店商品销售流水 ODS:GetGoodsSalesList -> orderGoodsLedgers 原始 JSON",
+ description="闂ㄥ簵鍟嗗搧閿€鍞祦姘?ODS锛欸etGoodsSalesList -> orderGoodsLedgers 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_PAYMENT",
@@ -386,7 +633,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="支付流水 ODS:GetPayLogListPage 原始 JSON",
+ description="鏀粯娴佹按 ODS锛欸etPayLogListPage 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_REFUND",
@@ -403,10 +650,10 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="退款流水 ODS:GetRefundPayLogList 原始 JSON",
+ description="閫€娆炬祦姘?ODS锛欸etRefundPayLogList 鍘熷 JSON",
),
OdsTaskSpec(
- code="ODS_COUPON_VERIFY",
+ code="ODS_PLATFORM_COUPON",
class_name="OdsCouponVerifyTask",
table_name="billiards_ods.platform_coupon_redemption_records",
endpoint="/Promotion/GetOfflineCouponConsumePageList",
@@ -420,7 +667,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="平台/团购券核销 ODS:GetOfflineCouponConsumePageList 原始 JSON",
+ description="骞冲彴/鍥㈣喘鍒告牳閿€ ODS锛欸etOfflineCouponConsumePageList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_MEMBER",
@@ -438,7 +685,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="会员档案 ODS:GetTenantMemberList -> tenantMemberInfos 原始 JSON",
+ description="浼氬憳妗f ODS锛欸etTenantMemberList -> tenantMemberInfos 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_MEMBER_CARD",
@@ -456,7 +703,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="会员储值卡 ODS:GetTenantMemberCardList -> tenantMemberCards 原始 JSON",
+ description="浼氬憳鍌ㄥ€煎崱 ODS锛欸etTenantMemberCardList -> tenantMemberCards 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_MEMBER_BALANCE",
@@ -474,7 +721,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="会员余额变动 ODS:GetMemberCardBalanceChange -> tenantMemberCardLogs 原始 JSON",
+ description="浼氬憳浣欓鍙樺姩 ODS锛欸etMemberCardBalanceChange -> tenantMemberCardLogs 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_RECHARGE_SETTLE",
@@ -483,19 +730,84 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
endpoint="/Site/GetRechargeSettleList",
data_path=("data",),
list_key="settleList",
- pk_columns=(),
+ time_fields=("rangeStartTime", "rangeEndTime"),
+ pk_columns=(_int_col("recharge_order_id", "settleList.id", "id", required=True),),
+ extra_columns=(
+ _int_col("tenant_id", "settleList.tenantId", "tenantId"),
+ _int_col("site_id", "settleList.siteId", "siteId", "siteProfile.id"),
+ ColumnSpec("site_name_snapshot", sources=("siteProfile.shop_name", "settleList.siteName")),
+ _int_col("member_id", "settleList.memberId", "memberId"),
+ ColumnSpec("member_name_snapshot", sources=("settleList.memberName", "memberName")),
+ ColumnSpec("member_phone_snapshot", sources=("settleList.memberPhone", "memberPhone")),
+ _int_col("tenant_member_card_id", "settleList.tenantMemberCardId", "tenantMemberCardId"),
+ ColumnSpec("member_card_type_name", sources=("settleList.memberCardTypeName", "memberCardTypeName")),
+ _int_col("settle_relate_id", "settleList.settleRelateId", "settleRelateId"),
+ _int_col("settle_type", "settleList.settleType", "settleType"),
+ ColumnSpec("settle_name", sources=("settleList.settleName", "settleName")),
+ _int_col("is_first", "settleList.isFirst", "isFirst"),
+ _int_col("settle_status", "settleList.settleStatus", "settleStatus"),
+ _decimal_col("pay_amount", "settleList.payAmount", "payAmount"),
+ _decimal_col("refund_amount", "settleList.refundAmount", "refundAmount"),
+ _decimal_col("point_amount", "settleList.pointAmount", "pointAmount"),
+ _decimal_col("cash_amount", "settleList.cashAmount", "cashAmount"),
+ _decimal_col("online_amount", "settleList.onlineAmount", "onlineAmount"),
+ _decimal_col("balance_amount", "settleList.balanceAmount", "balanceAmount"),
+ _decimal_col("card_amount", "settleList.cardAmount", "cardAmount"),
+ _decimal_col("coupon_amount", "settleList.couponAmount", "couponAmount"),
+ _decimal_col("recharge_card_amount", "settleList.rechargeCardAmount", "rechargeCardAmount"),
+ _decimal_col("gift_card_amount", "settleList.giftCardAmount", "giftCardAmount"),
+ _decimal_col("prepay_money", "settleList.prepayMoney", "prepayMoney"),
+ _decimal_col("consume_money", "settleList.consumeMoney", "consumeMoney"),
+ _decimal_col("goods_money", "settleList.goodsMoney", "goodsMoney"),
+ _decimal_col("real_goods_money", "settleList.realGoodsMoney", "realGoodsMoney"),
+ _decimal_col("table_charge_money", "settleList.tableChargeMoney", "tableChargeMoney"),
+ _decimal_col("service_money", "settleList.serviceMoney", "serviceMoney"),
+ _decimal_col("activity_discount", "settleList.activityDiscount", "activityDiscount"),
+ _decimal_col("all_coupon_discount", "settleList.allCouponDiscount", "allCouponDiscount"),
+ _decimal_col("goods_promotion_money", "settleList.goodsPromotionMoney", "goodsPromotionMoney"),
+ _decimal_col("assistant_promotion_money", "settleList.assistantPromotionMoney", "assistantPromotionMoney"),
+ _decimal_col("assistant_pd_money", "settleList.assistantPdMoney", "assistantPdMoney"),
+ _decimal_col("assistant_cx_money", "settleList.assistantCxMoney", "assistantCxMoney"),
+ _decimal_col("assistant_manual_discount", "settleList.assistantManualDiscount", "assistantManualDiscount"),
+ _decimal_col("coupon_sale_amount", "settleList.couponSaleAmount", "couponSaleAmount"),
+ _decimal_col("member_discount_amount", "settleList.memberDiscountAmount", "memberDiscountAmount"),
+ _decimal_col("point_discount_price", "settleList.pointDiscountPrice", "pointDiscountPrice"),
+ _decimal_col("point_discount_cost", "settleList.pointDiscountCost", "pointDiscountCost"),
+ _decimal_col("adjust_amount", "settleList.adjustAmount", "adjustAmount"),
+ _decimal_col("rounding_amount", "settleList.roundingAmount", "roundingAmount"),
+ _int_col("payment_method", "settleList.paymentMethod", "paymentMethod"),
+ _bool_col("can_be_revoked", "settleList.canBeRevoked", "canBeRevoked"),
+ _bool_col("is_bind_member", "settleList.isBindMember", "isBindMember"),
+ _bool_col("is_activity", "settleList.isActivity", "isActivity"),
+ _bool_col("is_use_coupon", "settleList.isUseCoupon", "isUseCoupon"),
+ _bool_col("is_use_discount", "settleList.isUseDiscount", "isUseDiscount"),
+ _int_col("operator_id", "settleList.operatorId", "operatorId"),
+ ColumnSpec("operator_name_snapshot", sources=("settleList.operatorName", "operatorName")),
+ _int_col("salesman_user_id", "settleList.salesManUserId", "salesmanUserId", "salesManUserId"),
+ ColumnSpec("salesman_name", sources=("settleList.salesManName", "salesmanName", "settleList.salesmanName")),
+ ColumnSpec("order_remark", sources=("settleList.orderRemark", "orderRemark")),
+ _int_col("table_id", "settleList.tableId", "tableId"),
+ _int_col("serial_number", "settleList.serialNumber", "serialNumber"),
+ _int_col("revoke_order_id", "settleList.revokeOrderId", "revokeOrderId"),
+ ColumnSpec("revoke_order_name", sources=("settleList.revokeOrderName", "revokeOrderName")),
+ ColumnSpec("revoke_time", sources=("settleList.revokeTime", "revokeTime")),
+ ColumnSpec("create_time", sources=("settleList.createTime", "createTime")),
+ ColumnSpec("pay_time", sources=("settleList.payTime", "payTime")),
+ ColumnSpec("site_profile", sources=("siteProfile",)),
+ ),
include_site_column=False,
- include_source_endpoint=False,
+ include_source_endpoint=True,
include_page_no=False,
include_page_size=False,
- include_fetched_at=False,
- include_record_index=True,
- conflict_columns_override=("source_file", "record_index"),
- requires_window=False,
- description="会员充值结算 ODS:GetRechargeSettleList -> settleList 原始 JSON",
+ include_fetched_at=True,
+ include_record_index=False,
+ conflict_columns_override=None,
+ requires_window=True,
+ description="?????? ODS?GetRechargeSettleList -> data.settleList ????",
),
+
OdsTaskSpec(
- code="ODS_PACKAGE",
+ code="ODS_GROUP_PACKAGE",
class_name="OdsPackageTask",
table_name="billiards_ods.group_buy_packages",
endpoint="/PackageCoupon/QueryPackageCouponList",
@@ -510,7 +822,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="团购套餐定义 ODS:QueryPackageCouponList -> packageCouponList 原始 JSON",
+ description="鍥㈣喘濂楅瀹氫箟 ODS锛歈ueryPackageCouponList -> packageCouponList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_GROUP_BUY_REDEMPTION",
@@ -528,7 +840,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="团购套餐核销 ODS:GetSiteTableUseDetails -> siteTableUseDetailsList 原始 JSON",
+ description="鍥㈣喘濂楅鏍搁攢 ODS锛欸etSiteTableUseDetails -> siteTableUseDetailsList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_INVENTORY_STOCK",
@@ -545,7 +857,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="库存汇总 ODS:GetGoodsStockReport 原始 JSON",
+ description="搴撳瓨姹囨€?ODS锛欸etGoodsStockReport 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_INVENTORY_CHANGE",
@@ -562,7 +874,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_fetched_at=False,
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
- description="库存变化记录 ODS:QueryGoodsOutboundReceipt -> queryDeliveryRecordsList 原始 JSON",
+ description="搴撳瓨鍙樺寲璁板綍 ODS锛歈ueryGoodsOutboundReceipt -> queryDeliveryRecordsList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_TABLES",
@@ -580,7 +892,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="台桌维表 ODS:GetSiteTables -> siteTables 原始 JSON",
+ description="鍙版缁磋〃 ODS锛欸etSiteTables -> siteTables 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_GOODS_CATEGORY",
@@ -598,7 +910,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="库存商品分类树 ODS:QueryPrimarySecondaryCategory -> goodsCategoryList 原始 JSON",
+ description="搴撳瓨鍟嗗搧鍒嗙被鏍?ODS锛歈ueryPrimarySecondaryCategory -> goodsCategoryList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_STORE_GOODS",
@@ -616,10 +928,10 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="门店商品档案 ODS:GetGoodsInventoryList -> orderGoodsList 原始 JSON",
+ description="闂ㄥ簵鍟嗗搧妗f ODS锛欸etGoodsInventoryList -> orderGoodsList 鍘熷 JSON",
),
OdsTaskSpec(
- code="ODS_TABLE_DISCOUNT",
+ code="ODS_TABLE_FEE_DISCOUNT",
class_name="OdsTableDiscountTask",
table_name="billiards_ods.table_fee_discount_records",
endpoint="/Site/GetTaiFeeAdjustList",
@@ -634,7 +946,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="台费折扣/调账 ODS:GetTaiFeeAdjustList -> taiFeeAdjustInfos 原始 JSON",
+ description="鍙拌垂鎶樻墸/璋冭处 ODS锛欸etTaiFeeAdjustList -> taiFeeAdjustInfos 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_TENANT_GOODS",
@@ -652,7 +964,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
include_record_index=True,
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
- description="租户商品档案 ODS:QueryTenantGoods -> tenantGoodsList 原始 JSON",
+ description="绉熸埛鍟嗗搧妗f ODS锛歈ueryTenantGoods -> tenantGoodsList 鍘熷 JSON",
),
OdsTaskSpec(
code="ODS_SETTLEMENT_TICKET",
@@ -671,7 +983,7 @@ ODS_TASK_SPECS: Tuple[OdsTaskSpec, ...] = (
conflict_columns_override=("source_file", "record_index"),
requires_window=False,
include_site_id=False,
- description="结账小票详情 ODS:GetOrderSettleTicketNew 原始 JSON",
+ description="缁撹处灏忕エ璇︽儏 ODS锛欸etOrderSettleTicketNew 鍘熷 JSON",
),
)
@@ -703,74 +1015,121 @@ class OdsSettlementTicketTask(BaseOdsTask):
def execute(self, cursor_data: dict | None = None) -> dict:
spec = self.SPEC
- context = self._build_context(cursor_data)
- store_id = TypeParser.parse_int(self.config.get("app.store_id")) or 0
-
- counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
- loader = GenericODSLoader(
- self.db,
- spec.table_name,
- self._resolve_columns(spec),
- list(spec.conflict_columns_override or ("source_file", "record_index")),
+ base_context = self._build_context(cursor_data)
+ segments = build_window_segments(
+ self.config,
+ base_context.window_start,
+ base_context.window_end,
+ tz=self.tz,
+ override_only=True,
)
+ if not segments:
+ segments = [(base_context.window_start, base_context.window_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info("%s: 窗口拆分为 %s 段", spec.code, total_segments)
+
+ store_id = TypeParser.parse_int(self.config.get("app.store_id")) or 0
+ counts_total = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+ segment_results: list[dict] = []
source_file = self._resolve_source_file_hint(spec)
try:
existing_ids = self._fetch_existing_ticket_ids()
- candidates = self._collect_settlement_ids(
- store_id, existing_ids, context.window_start, context.window_end
- )
- candidates = [cid for cid in candidates if cid and cid not in existing_ids]
- counts["fetched"] = len(candidates)
-
- if not candidates:
+ for idx, (seg_start, seg_end) in enumerate(segments, start=1):
+ context = self._build_context_for_window(seg_start, seg_end, cursor_data)
self.logger.info(
- "%s: 窗口[%s ~ %s] 未发现需要抓取的小票",
+ "%s: 开始执行(%s/%s),窗口[%s ~ %s]",
spec.code,
+ idx,
+ total_segments,
context.window_start,
context.window_end,
)
- return self._build_result("SUCCESS", counts)
- payloads, skipped = self._fetch_ticket_payloads(candidates)
- counts["skipped"] += skipped
- rows: list[dict] = []
- for idx, payload in enumerate(payloads):
- row = self._build_row(
- spec=spec,
- store_id=store_id,
- record=payload,
- page_no=None,
- page_size_value=None,
- source_file=source_file,
- record_index=idx if spec.include_record_index else None,
+ candidates = self._collect_settlement_ids(
+ store_id, existing_ids, context.window_start, context.window_end
)
- if row is None:
- counts["skipped"] += 1
- continue
- rows.append(row)
+ candidates = [cid for cid in candidates if cid and cid not in existing_ids]
+ segment_counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+ segment_counts["fetched"] = len(candidates)
+
+ if not candidates:
+ self.logger.info(
+ "%s: 窗口[%s ~ %s] 未发现需要抓取的小票",
+ spec.code,
+ context.window_start,
+ context.window_end,
+ )
+ self._accumulate_counts(counts_total, segment_counts)
+ if total_segments > 1:
+ segment_results.append(
+ {
+ "window": {
+ "start": context.window_start,
+ "end": context.window_end,
+ "minutes": context.window_minutes,
+ },
+ "counts": segment_counts,
+ }
+ )
+ continue
+
+ payloads, skipped = self._fetch_ticket_payloads(candidates)
+ segment_counts["skipped"] += skipped
+ inserted, skipped2 = self._insert_records_schema_aware(
+ table=spec.table_name,
+ records=payloads,
+ response_payload=None,
+ source_file=source_file,
+ source_endpoint=spec.endpoint,
+ )
+ segment_counts["inserted"] += inserted
+ segment_counts["skipped"] += skipped2
+
+ self.db.commit()
+ existing_ids.update(candidates)
+ self._accumulate_counts(counts_total, segment_counts)
+ if total_segments > 1:
+ segment_results.append(
+ {
+ "window": {
+ "start": context.window_start,
+ "end": context.window_end,
+ "minutes": context.window_minutes,
+ },
+ "counts": segment_counts,
+ }
+ )
- inserted, updated, _ = loader.upsert_rows(rows)
- counts["inserted"] += inserted
- counts["updated"] += updated
- self.db.commit()
self.logger.info(
- "%s: 小票抓取完成,候选=%s 插入=%s 更新=%s 跳过=%s",
+ "%s: 小票抓取完成,抓取=%s 插入=%s 更新=%s 跳过=%s",
spec.code,
- len(candidates),
- inserted,
- updated,
- counts["skipped"],
+ counts_total["fetched"],
+ counts_total["inserted"],
+ 0,
+ counts_total["skipped"],
)
- return self._build_result("SUCCESS", counts)
+ result = self._build_result("SUCCESS", counts_total)
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+ result["window"] = {
+ "start": overall_start,
+ "end": overall_end,
+ "minutes": calc_window_minutes(overall_start, overall_end),
+ }
+ if segment_results:
+ result["segments"] = segment_results
+ result["request_params"] = {"candidates": counts_total["fetched"]}
+ return result
except Exception:
- counts["errors"] += 1
+ counts_total["errors"] += 1
self.db.rollback()
self.logger.error("%s: 小票抓取失败", spec.code, exc_info=True)
raise
- # ------------------------------------------------------------------ helpers
def _fetch_existing_ticket_ids(self) -> set[int]:
sql = """
SELECT DISTINCT
@@ -782,7 +1141,7 @@ class OdsSettlementTicketTask(BaseOdsTask):
try:
rows = self.db.query(sql)
except Exception:
- self.logger.warning("查询已有小票失败,按空集处理", exc_info=True)
+ self.logger.warning("鏌ヨ宸叉湁灏忕エ澶辫触锛屾寜绌洪泦澶勭悊", exc_info=True)
return set()
return {
@@ -819,7 +1178,7 @@ class OdsSettlementTicketTask(BaseOdsTask):
try:
rows = self.db.query(sql, params)
except Exception:
- self.logger.warning("读取支付流水以获取结算单ID失败,将尝试调用支付接口回退", exc_info=True)
+ self.logger.warning("璇诲彇鏀粯娴佹按浠ヨ幏鍙栫粨绠楀崟ID澶辫触锛屽皢灏濊瘯璋冪敤鏀粯鎺ュ彛鍥為€€", exc_info=True)
return set()
return {
@@ -853,7 +1212,7 @@ class OdsSettlementTicketTask(BaseOdsTask):
if relate_id:
candidate_ids.add(relate_id)
except Exception:
- self.logger.warning("调用支付接口获取结算单ID失败,当前批次将跳过回退来源", exc_info=True)
+ self.logger.warning("璋冪敤鏀粯鎺ュ彛鑾峰彇缁撶畻鍗旾D澶辫触锛屽綋鍓嶆壒娆″皢璺宠繃鍥為€€鏉ユ簮", exc_info=True)
return candidate_ids
def _fetch_ticket_payload(self, order_settle_id: int):
@@ -869,10 +1228,10 @@ class OdsSettlementTicketTask(BaseOdsTask):
payload = response
except Exception:
self.logger.warning(
- "调用小票接口失败 orderSettleId=%s", order_settle_id, exc_info=True
+ "璋冪敤灏忕エ鎺ュ彛澶辫触 orderSettleId=%s", order_settle_id, exc_info=True
)
if isinstance(payload, dict) and isinstance(payload.get("data"), list) and len(payload["data"]) == 1:
- # 本地桩/回放可能把响应包装成单元素 list,这里展开以贴近真实结构
+ # 鏈湴妗?鍥炴斁鍙兘鎶婂搷搴斿寘瑁呮垚鍗曞厓绱?list锛岃繖閲屽睍寮€浠ヨ创杩戠湡瀹炵粨鏋?
payload = payload["data"][0]
return payload
@@ -899,27 +1258,29 @@ def _build_task_class(spec: OdsTaskSpec) -> Type[BaseOdsTask]:
ENABLED_ODS_CODES = {
- "ODS_ASSISTANT_ACCOUNTS",
+ "ODS_ASSISTANT_ACCOUNT",
"ODS_ASSISTANT_LEDGER",
"ODS_ASSISTANT_ABOLISH",
"ODS_INVENTORY_CHANGE",
"ODS_INVENTORY_STOCK",
- "ODS_PACKAGE",
+ "ODS_GROUP_PACKAGE",
"ODS_GROUP_BUY_REDEMPTION",
"ODS_MEMBER",
"ODS_MEMBER_BALANCE",
"ODS_MEMBER_CARD",
"ODS_PAYMENT",
"ODS_REFUND",
- "ODS_COUPON_VERIFY",
+ "ODS_PLATFORM_COUPON",
"ODS_RECHARGE_SETTLE",
+ "ODS_TABLE_USE",
"ODS_TABLES",
"ODS_GOODS_CATEGORY",
"ODS_STORE_GOODS",
- "ODS_TABLE_DISCOUNT",
+ "ODS_TABLE_FEE_DISCOUNT",
+ "ODS_STORE_GOODS_SALES",
"ODS_TENANT_GOODS",
"ODS_SETTLEMENT_TICKET",
- "ODS_ORDER_SETTLE",
+ "ODS_SETTLEMENT_RECORDS",
}
ODS_TASK_CLASSES: Dict[str, Type[BaseOdsTask]] = {
diff --git a/etl_billiards/tasks/payments_dwd_task.py b/etl_billiards/tasks/payments_dwd_task.py
index 2bcb2b6..c169b03 100644
--- a/etl_billiards/tasks/payments_dwd_task.py
+++ b/etl_billiards/tasks/payments_dwd_task.py
@@ -1,8 +1,9 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
from .base_dwd_task import BaseDwdTask
from loaders.facts.payment import PaymentLoader
from models.parsers import TypeParser
import json
+from utils.windowing import build_window_segments
class PaymentsDwdTask(BaseDwdTask):
"""
@@ -17,8 +18,20 @@ class PaymentsDwdTask(BaseDwdTask):
def execute(self) -> dict:
self.logger.info(f"Starting {self.get_task_code()} task")
- window_start, window_end, _ = self._get_time_window()
- self.logger.info(f"Processing window: {window_start} to {window_end}")
+ base_start, base_end, _ = self._get_time_window()
+ segments = build_window_segments(
+ self.config,
+ base_start,
+ base_end,
+ tz=self.tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(base_start, base_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info(f"{self.get_task_code()}: ????? {total_segments} ?")
loader = PaymentLoader(self.db, logger=self.logger)
store_id = self.config.get("app.store_id")
@@ -27,36 +40,42 @@ class PaymentsDwdTask(BaseDwdTask):
total_updated = 0
total_skipped = 0
- # Iterate ODS Data
- batches = self.iter_ods_rows(
- table_name="billiards_ods.ods_payment_record",
- columns=["site_id", "pay_id", "payload", "fetched_at"],
- start_time=window_start,
- end_time=window_end
- )
+ for idx, (window_start, window_end) in enumerate(segments, start=1):
+ self.logger.info(
+ f"Processing window {idx}/{total_segments}: {window_start} to {window_end}"
+ )
+ batches = self.iter_ods_rows(
+ table_name="billiards_ods.payment_transactions",
+ columns=["site_id", "pay_id", "payload", "fetched_at"],
+ start_time=window_start,
+ end_time=window_end
+ )
- for batch in batches:
- if not batch:
- continue
-
- parsed_rows = []
- for row in batch:
- payload = self.parse_payload(row)
- if not payload:
+ for batch in batches:
+ if not batch:
continue
-
- parsed = self._parse_payment(payload, store_id)
- if parsed:
- parsed_rows.append(parsed)
-
- if parsed_rows:
- inserted, updated, skipped = loader.upsert_payments(parsed_rows, store_id)
- total_inserted += inserted
- total_updated += updated
- total_skipped += skipped
- self.db.commit()
-
+ parsed_rows = []
+ for row in batch:
+ payload = self.parse_payload(row)
+ if not payload:
+ continue
+
+ parsed = self._parse_payment(payload, store_id)
+ if parsed:
+ parsed_rows.append(parsed)
+
+ if parsed_rows:
+ inserted, updated, skipped = loader.upsert_payments(parsed_rows, store_id)
+ total_inserted += inserted
+ total_updated += updated
+ total_skipped += skipped
+
+ self.db.commit()
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+
self.logger.info(
"Task %s completed. inserted=%s updated=%s skipped=%s",
self.get_task_code(),
@@ -64,7 +83,7 @@ class PaymentsDwdTask(BaseDwdTask):
total_updated,
total_skipped,
)
-
+
return {
"status": "SUCCESS",
"counts": {
@@ -72,8 +91,8 @@ class PaymentsDwdTask(BaseDwdTask):
"updated": total_updated,
"skipped": total_skipped,
},
- "window_start": window_start,
- "window_end": window_end,
+ "window_start": overall_start,
+ "window_end": overall_end,
}
def _parse_payment(self, raw: dict, store_id: int) -> dict:
@@ -136,3 +155,4 @@ class PaymentsDwdTask(BaseDwdTask):
except Exception as e:
self.logger.warning(f"Error parsing payment: {e}")
return None
+
diff --git a/etl_billiards/tasks/ticket_dwd_task.py b/etl_billiards/tasks/ticket_dwd_task.py
index 34f76e2..58ac47c 100644
--- a/etl_billiards/tasks/ticket_dwd_task.py
+++ b/etl_billiards/tasks/ticket_dwd_task.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from .base_dwd_task import BaseDwdTask
from loaders.facts.ticket import TicketLoader
+from utils.windowing import build_window_segments
class TicketDwdTask(BaseDwdTask):
"""
@@ -19,51 +20,66 @@ class TicketDwdTask(BaseDwdTask):
def execute(self) -> dict:
self.logger.info(f"Starting {self.get_task_code()} task")
- # 1. Get Time Window (Incremental Load)
- window_start, window_end, _ = self._get_time_window()
- self.logger.info(f"Processing window: {window_start} to {window_end}")
+ base_start, base_end, _ = self._get_time_window()
+ segments = build_window_segments(
+ self.config,
+ base_start,
+ base_end,
+ tz=self.tz,
+ override_only=True,
+ )
+ if not segments:
+ segments = [(base_start, base_end)]
+
+ total_segments = len(segments)
+ if total_segments > 1:
+ self.logger.info(f"{self.get_task_code()}: ????? {total_segments} ?")
- # 2. Initialize Loader
loader = TicketLoader(self.db, logger=self.logger)
store_id = self.config.get("app.store_id")
total_inserted = 0
total_errors = 0
- # 3. Iterate ODS Data
- # We query ods_ticket_detail based on fetched_at
- batches = self.iter_ods_rows(
- table_name="billiards_ods.settlement_ticket_details",
- columns=["payload", "fetched_at", "source_file", "record_index"],
- start_time=window_start,
- end_time=window_end
+ for idx, (window_start, window_end) in enumerate(segments, start=1):
+ self.logger.info(
+ f"Processing window {idx}/{total_segments}: {window_start} to {window_end}"
+ )
+ batches = self.iter_ods_rows(
+ table_name="billiards_ods.settlement_ticket_details",
+ columns=["payload", "fetched_at", "source_file", "record_index"],
+ start_time=window_start,
+ end_time=window_end
+ )
+
+ for batch in batches:
+ if not batch:
+ continue
+
+ tickets = []
+ for row in batch:
+ payload = self.parse_payload(row)
+ if payload:
+ tickets.append(payload)
+
+ inserted, errors = loader.process_tickets(tickets, store_id)
+ total_inserted += inserted
+ total_errors += errors
+
+ self.db.commit()
+
+ overall_start = segments[0][0]
+ overall_end = segments[-1][1]
+
+ self.logger.info(
+ f"Task {self.get_task_code()} completed. Inserted: {total_inserted}, Errors: {total_errors}"
)
- for batch in batches:
- if not batch:
- continue
-
- # Extract payloads
- tickets = []
- for row in batch:
- payload = self.parse_payload(row)
- if payload:
- tickets.append(payload)
-
- # Process Batch
- inserted, errors = loader.process_tickets(tickets, store_id)
- total_inserted += inserted
- total_errors += errors
-
- # 4. Commit
- self.db.commit()
-
- self.logger.info(f"Task {self.get_task_code()} completed. Inserted: {total_inserted}, Errors: {total_errors}")
-
return {
"status": "success",
"inserted": total_inserted,
"errors": total_errors,
- "window_start": window_start.isoformat(),
- "window_end": window_end.isoformat()
+ "window_start": overall_start.isoformat(),
+ "window_end": overall_end.isoformat()
}
+
diff --git a/etl_billiards/tests/unit/task_test_utils.py b/etl_billiards/tests/unit/task_test_utils.py
index a21954b..47ef95e 100644
--- a/etl_billiards/tests/unit/task_test_utils.py
+++ b/etl_billiards/tests/unit/task_test_utils.py
@@ -4,6 +4,8 @@ from __future__ import annotations
import json
import os
+import re
+from types import SimpleNamespace
from contextlib import contextmanager
from dataclasses import dataclass
from pathlib import Path
@@ -99,16 +101,87 @@ def dump_offline_payload(spec: TaskSpec, archive_dir: Path) -> Path:
class FakeCursor:
"""极简游标桩对象,记录 SQL/参数并支持上下文管理,供 FakeDBOperations 与 SCD2Handler 使用。"""
- def __init__(self, recorder: List[Dict]):
+ def __init__(self, recorder: List[Dict], db_ops=None):
self.recorder = recorder
+ self._db_ops = db_ops
+ self._pending_rows: List[Tuple] = []
+ self._fetchall_rows: List[Tuple] = []
+ self.rowcount = 0
+ self.connection = SimpleNamespace(encoding="UTF8")
# pylint: disable=unused-argument
def execute(self, sql: str, params=None):
- self.recorder.append({"sql": sql.strip(), "params": params})
+ sql_text = sql.decode("utf-8", errors="ignore") if isinstance(sql, (bytes, bytearray)) else str(sql)
+ self.recorder.append({"sql": sql_text.strip(), "params": params})
+ self._fetchall_rows = []
+
+ # Handle information_schema queries for schema-aware inserts.
+ lowered = sql_text.lower()
+ if "from information_schema.columns" in lowered:
+ table_name = None
+ if params and len(params) >= 2:
+ table_name = params[1]
+ self._fetchall_rows = self._fake_columns(table_name)
+ return
+ if "from information_schema.table_constraints" in lowered:
+ self._fetchall_rows = []
+ return
+
+ if self._pending_rows:
+ self.rowcount = len(self._pending_rows)
+ self._record_upserts(sql_text)
+ self._pending_rows = []
+ else:
+ self.rowcount = 0
def fetchone(self):
return None
+ def fetchall(self):
+ return list(self._fetchall_rows)
+
+ def mogrify(self, template, args):
+ self._pending_rows.append(tuple(args))
+ return b"(?)"
+
+ def _record_upserts(self, sql_text: str):
+ if not self._db_ops:
+ return
+ match = re.search(r"insert\s+into\s+[^\(]+\(([^)]*)\)\s+values", sql_text, re.I)
+ if not match:
+ return
+ columns = [c.strip().strip('"') for c in match.group(1).split(",")]
+ rows = []
+ for idx, row in enumerate(self._pending_rows):
+ if len(row) != len(columns):
+ continue
+ row_dict = {}
+ for col, val in zip(columns, row):
+ if col == "record_index" and val in (None, ""):
+ row_dict[col] = idx
+ continue
+ if hasattr(val, "adapted"):
+ row_dict[col] = json.dumps(val.adapted, ensure_ascii=False)
+ else:
+ row_dict[col] = val
+ rows.append(row_dict)
+ if rows:
+ self._db_ops.upserts.append(
+ {"sql": sql_text.strip(), "count": len(rows), "page_size": len(rows), "rows": rows}
+ )
+
+ @staticmethod
+ def _fake_columns(_table_name: str | None) -> List[Tuple[str, str, str]]:
+ return [
+ ("id", "bigint", "int8"),
+ ("sitegoodsstockid", "bigint", "int8"),
+ ("record_index", "integer", "int4"),
+ ("source_file", "text", "text"),
+ ("source_endpoint", "text", "text"),
+ ("fetched_at", "timestamp with time zone", "timestamptz"),
+ ("payload", "jsonb", "jsonb"),
+ ]
+
def __enter__(self):
return self
@@ -119,11 +192,12 @@ class FakeCursor:
class FakeConnection:
"""仿 psycopg 连接对象,仅满足 SCD2Handler 对 cursor 的最小需求,并缓存执行过的语句。"""
- def __init__(self):
+ def __init__(self, db_ops):
self.statements: List[Dict] = []
+ self._db_ops = db_ops
def cursor(self):
- return FakeCursor(self.statements)
+ return FakeCursor(self.statements, self._db_ops)
class FakeDBOperations:
@@ -134,7 +208,7 @@ class FakeDBOperations:
self.executes: List[Dict] = []
self.commits = 0
self.rollbacks = 0
- self.conn = FakeConnection()
+ self.conn = FakeConnection(self)
# Pre-seeded query results (FIFO) to let tests control DB-returned rows
self.query_results: List[List[Dict]] = []
diff --git a/etl_billiards/tests/unit/test_config.py b/etl_billiards/tests/unit/test_config.py
index c79bc4d..861f3c7 100644
--- a/etl_billiards/tests/unit/test_config.py
+++ b/etl_billiards/tests/unit/test_config.py
@@ -6,7 +6,7 @@ from config.defaults import DEFAULTS
def test_config_load():
"""测试配置加载"""
- config = AppConfig.load()
+ config = AppConfig.load({"app": {"store_id": 1}})
assert config.get("app.timezone") == DEFAULTS["app"]["timezone"]
def test_config_override():
@@ -19,6 +19,6 @@ def test_config_override():
def test_config_get_nested():
"""测试嵌套配置获取"""
- config = AppConfig.load()
+ config = AppConfig.load({"app": {"store_id": 1}})
assert config.get("db.batch_size") == 1000
assert config.get("nonexistent.key", "default") == "default"
diff --git a/etl_billiards/tests/unit/test_endpoint_routing.py b/etl_billiards/tests/unit/test_endpoint_routing.py
new file mode 100644
index 0000000..4a81030
--- /dev/null
+++ b/etl_billiards/tests/unit/test_endpoint_routing.py
@@ -0,0 +1,68 @@
+# -*- coding: utf-8 -*-
+"""Unit tests for recent/former endpoint routing."""
+
+import sys
+from datetime import datetime
+from pathlib import Path
+from zoneinfo import ZoneInfo
+
+import pytest
+
+PROJECT_ROOT = Path(__file__).resolve().parents[2]
+if str(PROJECT_ROOT) not in sys.path:
+ sys.path.insert(0, str(PROJECT_ROOT))
+
+from api.endpoint_routing import plan_calls, recent_boundary
+
+
+TZ = ZoneInfo("Asia/Shanghai")
+
+
+def _now():
+ return datetime(2025, 12, 18, 10, 0, 0, tzinfo=TZ)
+
+
+def test_recent_boundary_month_start():
+ b = recent_boundary(_now())
+ assert b.isoformat() == "2025-09-01T00:00:00+08:00"
+
+
+def test_paylog_routes_to_former_when_old_window():
+ params = {"siteId": 1, "StartPayTime": "2025-08-01 00:00:00", "EndPayTime": "2025-08-02 00:00:00"}
+ calls = plan_calls("/PayLog/GetPayLogListPage", params, now=_now(), tz=TZ)
+ assert [c.endpoint for c in calls] == ["/PayLog/GetFormerPayLogListPage"]
+
+
+def test_coupon_usage_stays_same_path_even_when_old():
+ params = {"siteId": 1, "startTime": "2025-08-01 00:00:00", "endTime": "2025-08-02 00:00:00"}
+ calls = plan_calls("/Promotion/GetOfflineCouponConsumePageList", params, now=_now(), tz=TZ)
+ assert [c.endpoint for c in calls] == ["/Promotion/GetOfflineCouponConsumePageList"]
+
+
+def test_goods_outbound_routes_to_queryformer_when_old():
+ params = {"siteId": 1, "startTime": "2025-08-01 00:00:00", "endTime": "2025-08-02 00:00:00"}
+ calls = plan_calls("/GoodsStockManage/QueryGoodsOutboundReceipt", params, now=_now(), tz=TZ)
+ assert [c.endpoint for c in calls] == ["/GoodsStockManage/QueryFormerGoodsOutboundReceipt"]
+
+
+def test_settlement_records_split_when_crossing_boundary():
+ params = {"siteId": 1, "rangeStartTime": "2025-08-15 00:00:00", "rangeEndTime": "2025-09-10 00:00:00"}
+ calls = plan_calls("/Site/GetAllOrderSettleList", params, now=_now(), tz=TZ)
+ assert [c.endpoint for c in calls] == ["/Site/GetFormerOrderSettleList", "/Site/GetAllOrderSettleList"]
+ assert calls[0].params["rangeEndTime"] == "2025-09-01 00:00:00"
+ assert calls[1].params["rangeStartTime"] == "2025-09-01 00:00:00"
+
+
+@pytest.mark.parametrize(
+ "endpoint",
+ [
+ "/PayLog/GetFormerPayLogListPage",
+ "/Site/GetFormerOrderSettleList",
+ "/GoodsStockManage/QueryFormerGoodsOutboundReceipt",
+ ],
+)
+def test_explicit_former_endpoint_not_rerouted(endpoint):
+ params = {"siteId": 1, "startTime": "2025-08-01 00:00:00", "endTime": "2025-08-02 00:00:00"}
+ calls = plan_calls(endpoint, params, now=_now(), tz=TZ)
+ assert [c.endpoint for c in calls] == [endpoint]
+
diff --git a/etl_billiards/tests/unit/test_ods_tasks.py b/etl_billiards/tests/unit/test_ods_tasks.py
index 4584e52..9431a14 100644
--- a/etl_billiards/tests/unit/test_ods_tasks.py
+++ b/etl_billiards/tests/unit/test_ods_tasks.py
@@ -1,4 +1,4 @@
-# -*- coding: utf-8 -*-
+# -*- coding: utf-8 -*-
"""Unit tests for the new ODS ingestion tasks."""
import logging
import os
@@ -22,21 +22,21 @@ def _build_config(tmp_path):
return create_test_config("ONLINE", archive_dir, temp_dir)
-def test_ods_assistant_accounts_ingest(tmp_path):
- """Ensure ODS_ASSISTANT_ACCOUNTS task stores raw payload with record_index dedup keys."""
+def test_assistant_accounts_masters_ingest(tmp_path):
+ """Ensure ODS_ASSISTANT_ACCOUNT stores raw payload with record_index dedup keys."""
config = _build_config(tmp_path)
sample = [
{
"id": 5001,
"assistant_no": "A01",
- "nickname": "小张",
+ "nickname": "灏忓紶",
}
]
api = FakeAPIClient({"/PersonnelManagement/SearchAssistantInfo": sample})
- task_cls = ODS_TASK_CLASSES["ODS_ASSISTANT_ACCOUNTS"]
+ task_cls = ODS_TASK_CLASSES["ODS_ASSISTANT_ACCOUNT"]
with get_db_operations() as db_ops:
- task = task_cls(config, db_ops, api, logging.getLogger("test_ods_assistant_accounts"))
+ task = task_cls(config, db_ops, api, logging.getLogger("test_assistant_accounts_masters"))
result = task.execute()
assert result["status"] == "SUCCESS"
@@ -49,21 +49,21 @@ def test_ods_assistant_accounts_ingest(tmp_path):
assert '"id": 5001' in row["payload"]
-def test_ods_inventory_change_ingest(tmp_path):
- """Ensure ODS_INVENTORY_CHANGE task stores raw payload with record_index dedup keys."""
+def test_goods_stock_movements_ingest(tmp_path):
+ """Ensure ODS_INVENTORY_CHANGE stores raw payload with record_index dedup keys."""
config = _build_config(tmp_path)
sample = [
{
"siteGoodsStockId": 123456,
"stockType": 1,
- "goodsName": "测试商品",
+ "goodsName": "娴嬭瘯鍟嗗搧",
}
]
api = FakeAPIClient({"/GoodsStockManage/QueryGoodsOutboundReceipt": sample})
task_cls = ODS_TASK_CLASSES["ODS_INVENTORY_CHANGE"]
with get_db_operations() as db_ops:
- task = task_cls(config, db_ops, api, logging.getLogger("test_ods_inventory_change"))
+ task = task_cls(config, db_ops, api, logging.getLogger("test_goods_stock_movements"))
result = task.execute()
assert result["status"] == "SUCCESS"
@@ -75,7 +75,7 @@ def test_ods_inventory_change_ingest(tmp_path):
assert '"siteGoodsStockId": 123456' in row["payload"]
-def test_ods_member_profiles_ingest(tmp_path):
+def test_member_profiless_ingest(tmp_path):
"""Ensure ODS_MEMBER task stores tenantMemberInfos raw JSON."""
config = _build_config(tmp_path)
sample = [{"tenantMemberInfos": [{"id": 101, "mobile": "13800000000"}]}]
@@ -110,14 +110,14 @@ def test_ods_payment_ingest(tmp_path):
def test_ods_settlement_records_ingest(tmp_path):
- """Ensure ODS_ORDER_SETTLE task stores settleList raw JSON."""
+ """Ensure ODS_SETTLEMENT_RECORDS stores settleList raw JSON."""
config = _build_config(tmp_path)
- sample = [{"data": {"settleList": [{"id": 701, "orderTradeNo": 8001}]}}]
+ sample = [{"id": 701, "orderTradeNo": 8001}]
api = FakeAPIClient({"/Site/GetAllOrderSettleList": sample})
- task_cls = ODS_TASK_CLASSES["ODS_ORDER_SETTLE"]
+ task_cls = ODS_TASK_CLASSES["ODS_SETTLEMENT_RECORDS"]
with get_db_operations() as db_ops:
- task = task_cls(config, db_ops, api, logging.getLogger("test_ods_order_settle"))
+ task = task_cls(config, db_ops, api, logging.getLogger("test_settlement_records"))
result = task.execute()
assert result["status"] == "SUCCESS"
@@ -158,3 +158,4 @@ def test_ods_settlement_ticket_by_payment_relate_ids(tmp_path):
and call.get("params", {}).get("orderSettleId") == 9001
for call in api.calls
)
+
diff --git a/etl_billiards/utils/logging_utils.py b/etl_billiards/utils/logging_utils.py
new file mode 100644
index 0000000..2c60674
--- /dev/null
+++ b/etl_billiards/utils/logging_utils.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+from __future__ import annotations
+
+import logging
+import sys
+from contextlib import contextmanager
+from datetime import datetime
+from pathlib import Path
+from typing import Iterator, TextIO
+
+
+class TeeStream:
+ def __init__(self, *streams: TextIO) -> None:
+ self._streams = streams
+
+ def write(self, data: str) -> int:
+ for stream in self._streams:
+ stream.write(data)
+ return len(data)
+
+ def flush(self) -> None:
+ for stream in self._streams:
+ stream.flush()
+
+ def isatty(self) -> bool:
+ return False
+
+ def fileno(self) -> int:
+ return self._streams[0].fileno()
+
+
+def build_log_path(log_dir: Path, prefix: str, tag: str = "") -> Path:
+ suffix = f"_{tag}" if tag else ""
+ stamp = datetime.now().strftime("%Y%m%d_%H%M%S")
+ return log_dir / f"{prefix}{suffix}_{stamp}.log"
+
+
+@contextmanager
+def configure_logging(
+ name: str,
+ log_file: Path | None,
+ *,
+ level: str = "INFO",
+ console: bool = True,
+ tee_std: bool = True,
+) -> Iterator[logging.Logger]:
+ logger = logging.getLogger(name)
+ logger.handlers.clear()
+ logger.setLevel(getattr(logging, level.upper(), logging.INFO))
+ logger.propagate = False
+
+ formatter = logging.Formatter(
+ "%(asctime)s [%(levelname)s] %(name)s: %(message)s",
+ "%Y-%m-%d %H:%M:%S",
+ )
+
+ original_stdout = sys.stdout
+ original_stderr = sys.stderr
+ log_fp: TextIO | None = None
+
+ try:
+ if log_file:
+ log_file.parent.mkdir(parents=True, exist_ok=True)
+ log_fp = open(log_file, "a", encoding="utf-8", buffering=1)
+ if tee_std:
+ if console:
+ sys.stdout = TeeStream(original_stdout, log_fp)
+ sys.stderr = TeeStream(original_stderr, log_fp)
+ else:
+ sys.stdout = log_fp
+ sys.stderr = log_fp
+ file_handler = logging.StreamHandler(log_fp)
+ file_handler.setFormatter(formatter)
+ logger.addHandler(file_handler)
+
+ if console:
+ console_handler = logging.StreamHandler(original_stdout)
+ console_handler.setFormatter(formatter)
+ logger.addHandler(console_handler)
+
+ yield logger
+ finally:
+ for handler in list(logger.handlers):
+ handler.flush()
+ handler.close()
+ logger.removeHandler(handler)
+ if log_fp:
+ log_fp.flush()
+ log_fp.close()
+ sys.stdout = original_stdout
+ sys.stderr = original_stderr
diff --git a/etl_billiards/utils/windowing.py b/etl_billiards/utils/windowing.py
new file mode 100644
index 0000000..b15ee21
--- /dev/null
+++ b/etl_billiards/utils/windowing.py
@@ -0,0 +1,97 @@
+# -*- coding: utf-8 -*-
+"""Time window helpers for ETL and validation tasks."""
+from __future__ import annotations
+
+from datetime import datetime, timedelta, time
+from typing import List, Tuple
+from zoneinfo import ZoneInfo
+
+
+def _ensure_tz(dt: datetime, tz: ZoneInfo | None) -> datetime:
+ if tz is None:
+ return dt
+ if dt.tzinfo is None:
+ return dt.replace(tzinfo=tz)
+ return dt.astimezone(tz)
+
+
+def _next_month_start(dt: datetime, tz: ZoneInfo | None) -> datetime:
+ year = dt.year
+ month = dt.month
+ if month == 12:
+ year += 1
+ month = 1
+ else:
+ month += 1
+ return datetime(year, month, 1, tzinfo=tz)
+
+
+def calc_window_minutes(start: datetime, end: datetime) -> int:
+ if end <= start:
+ return 0
+ return max(1, int((end - start).total_seconds() // 60))
+
+
+def split_window(
+ start: datetime,
+ end: datetime,
+ *,
+ tz: ZoneInfo | None,
+ split_unit: str | None,
+ compensation_hours: int | float | None,
+) -> List[Tuple[datetime, datetime]]:
+ start = _ensure_tz(start, tz)
+ end = _ensure_tz(end, tz)
+
+ comp = int(compensation_hours or 0)
+ if comp:
+ start = start - timedelta(hours=comp)
+ end = end + timedelta(hours=comp)
+
+ if end <= start:
+ return []
+
+ unit = (split_unit or "").strip().lower()
+ if unit in ("", "none", "off", "false", "0"):
+ return [(start, end)]
+
+ if unit not in ("month", "monthly"):
+ return [(start, end)]
+
+ windows: List[Tuple[datetime, datetime]] = []
+ cur = start
+ while cur < end:
+ boundary = _next_month_start(cur, tz)
+ nxt = boundary if boundary < end else end
+ if nxt <= cur:
+ break
+ windows.append((cur, nxt))
+ cur = nxt
+ return windows
+
+
+def build_window_segments(
+ cfg,
+ start: datetime,
+ end: datetime,
+ *,
+ tz: ZoneInfo | None,
+ override_only: bool,
+) -> List[Tuple[datetime, datetime]]:
+ split_unit = cfg.get("run.window_split.unit", "month")
+ compensation_hours = cfg.get("run.window_split.compensation_hours", 0)
+
+ if override_only:
+ override_start = cfg.get("run.window_override.start")
+ override_end = cfg.get("run.window_override.end")
+ if not (override_start and override_end):
+ split_unit = "none"
+ compensation_hours = 0
+
+ return split_window(
+ start,
+ end,
+ tz=tz,
+ split_unit=split_unit,
+ compensation_hours=compensation_hours,
+ )
diff --git a/requirements.txt b/requirements.txt
index 1a61b91..b903978 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -2,3 +2,4 @@ requests
psycopg2-binary
python-dateutil
tzdata
+flask>=2.3
diff --git a/tmp/20251121-task.txt b/tmp/20251121-task.txt
new file mode 100644
index 0000000..5b3cb2d
--- /dev/null
+++ b/tmp/20251121-task.txt
@@ -0,0 +1,1361 @@
+2. 鏁颁粨鍒嗗眰缁撴瀯鎬昏
+
+鏈」鐩噰鐢ㄥ吀鍨嬬殑涓夊眰鏁颁粨鍒嗗眰浣撶郴锛?
+
+- **ODS锛圤perational Data Store锛屾搷浣滄暟鎹眰锛?*锛?
+ 浠モ€滆创婧愨€濇柟寮忔壙鎺ヤ笂娓?JSON 鏁版嵁锛屼竴鏉¤褰曞敖閲忓搴斾笂娓镐竴鏉′笟鍔¤褰曪紝浠呭仛鏈€杞诲害鐨勬暟鎹被鍨嬭鑼冧笌瀛楁琛ュ厖锛屼笉鍋氫笟鍔″彛寰勬敼閫犮€?
+- **DWD锛圖ata Warehouse Detail锛屾槑缁嗘暟鎹眰锛?*锛?
+ 鍦?ODS 鍩虹涓婅繘琛屾竻娲椼€佹爣鍑嗗寲涓庤交搴︽眹鎬伙紝褰㈡垚鏍囧噯鐨勩€屼簨瀹炶〃 + 缁村害琛ㄣ€嶆ā鍨嬶紝浣滀负鍚庣画 DWS 鍜屾姤琛ㄧ殑缁熶竴鏄庣粏鏁版嵁婧愩€?
+- **DWS锛圖ata Warehouse Service锛屾眹鎬绘湇鍔″眰锛?*锛?
+ 闈㈠悜鍏蜂綋缁忚惀鍒嗘瀽鍦烘櫙鐨勬眹鎬诲琛ㄦ垨涓婚姹囨€昏〃锛屾湰鏈熼噸鐐逛负銆岃鍗曠矑搴︺€嶇殑姹囨€伙紙姣忕瑪缁撹处涓€琛岋級锛屽悗缁彲鎵╁睍鏃ョ矑搴︺€佸姪鏁欑哗鏁堢矑搴︾瓑瀹借〃銆?
+
+### 2.1 鍚勫眰琛ㄦ竻鍗?
+
+#### 2.1.1 ODS 灞傝〃锛堟簮鏁版嵁闀滃儚锛?
+
+ODS 灞傛寜涓婃父 JSON 鏂囦欢涓€涓€鏄犲皠锛屼繚鐣欐簮绯荤粺瀛楁锛屽瓧娈靛懡鍚嶅敖閲忓榻愭簮瀛楁銆?
+
+| 琛ㄥ悕 | 绮掑害鎻忚堪 | 涓昏鏉ユ簮 JSON / 璇存槑 |
+|------------------------------|------------------------------------|------------------------------------|
+| `member_profiles` | 浼氬憳妗f锛? 琛?= 1 涓細鍛樿处鍙? | 浼氬憳妗f.JSON |
+| `member_stored_value_cards` | 浼氬憳鍗¤褰曪紝1 琛?= 1 寮犲崱 | 鍌ㄥ€煎崱鍒楄〃.JSON |
+| `member_balance_changes` | 浣欓鍙樻洿璁板綍锛? 琛?= 1 娆′綑棰濆彉鍔? | 浣欓鍙樺姩.JSON |
+| `ods_recharge_record` | 鍏呭€艰褰曪紝1 琛?= 1 绗斿厖鍊间氦鏄? | 鍏呭€艰褰?JSON |
+| `ods_product` | 绉熸埛绾у晢鍝佹。妗? | 鍟嗗搧妗f.JSON |
+| `ods_store_product` | 闂ㄥ簵鍟嗗搧妗f锛岄棬搴楃淮搴︾殑鍟嗗搧閰嶇疆 | 闂ㄥ簵鍟嗗搧妗f.JSON |
+| `ods_store_sale_item` | 鍟嗗搧閿€鍞槑缁嗭紝1 琛?= 1 涓攢鍞 | 闂ㄥ簵閿€鍞褰?JSON |
+| `ods_table_info` | 鍙版妗f锛? 琛?= 1 寮犲彴/鍖呭帰 | 鍙版鍒楄〃.JSON |
+| `table_fee_transactions_log` | 鍙拌垂娴佹按锛? 琛?= 1 绗斿彴妗屼娇鐢ㄨ褰? | 鍙拌垂娴佹按.JSON |
+| `ods_table_fee_adjust` | 鍙拌垂鎵撴姌璁板綍锛? 琛?= 1 娆′汉宸ユ姌鎵? | 鍙拌垂鎵撴姌.JSON |
+| `assistant_accounts_master` | 鍔╂暀璐﹀彿妗f锛? 琛?= 1 涓姪鏁欒处鍙? | 鍔╂暀璐﹀彿.JSON |
+| `ods_assistant_service_log` | 鍔╂暀鏈嶅姟娴佹按锛? 琛?= 1 鏉″姪鏁欐湇鍔? | 鍔╂暀娴佹按.JSON |
+| `ods_assistant_cancel_log` | 鍔╂暀搴熼櫎璁板綍锛? 琛?= 1 娆℃湇鍔″彇娑? | 鍔╂暀搴熼櫎.JSON |
+| `group_buy_packages` | 鍥㈣喘濂楅瀹氫箟 | 鍥㈣喘濂楅瀹氫箟.JSON |
+| `group_buy_packages_log` | 鍥㈣喘濂楅浣跨敤娴佹按 | 鍥㈣喘濂楅浣跨敤.JSON |
+| `ods_platform_coupon_log` | 骞冲彴楠屽埜璁板綍 | 骞冲彴楠屽埜.JSON |
+| `payment_transactions` | 鏀粯璁板綍锛? 琛?= 1 涓敮浠樻笭閬撴祦姘? | 鏀粯璁板綍.JSON |
+| `refund_transactions` | 閫€娆捐褰曪紝1 琛?= 1 涓€€娆炬祦姘? | 閫€娆捐褰?JSON |
+| `ods_order_receipt_detail` | 缁撹处灏忕エ璇︽儏锛? 琛?= 1 寮犵粨绠楀皬绁? | 灏忕エ璇︽儏 JSON锛堝惈 siteProfile 蹇収锛?|
+
+> 璇存槑锛氭湭鏉ュ鏋滀笂娓告柊澧?JSON 绫诲瀷锛堝搴撳瓨鏄庣粏銆佸椁愬畾涔夌瓑锛夛紝鎸変笂杩板懡鍚嶈鑼冩墿灞曞搴?ODS 琛ㄥ嵆鍙€?
+
+#### 2.1.2 DWD 灞傝〃锛堢淮搴?+ 鏄庣粏浜嬪疄锛?
+
+DWD 灞傚湪 ODS 鍩虹涓婂仛娓呮礂銆佸綊涓€鍖栧懡鍚嶄笌涓氬姟瑙勫垯鏁寸悊锛屽舰鎴愭湰鏈熺殑鏍稿績浜嬪疄涓庣淮搴︺€?
+
+**缁村害琛紙Dim锛夛細**
+
+| 琛ㄥ悕 | 鎻忚堪 | 璇存槑 |
+|------------------------|------------------------------|-------------------------------|
+| `dim_tenant` | 绉熸埛/鍝佺墝缁村害 | 鍝佺墝绾т富鏁版嵁锛堝鏈楁湕妗岀悆锛? |
+| `dim_site` | 闂ㄥ簵缁村害 | 缁熶竴鎵胯浇闂ㄥ簵涓绘暟鎹紙鏂板锛? |
+| `dim_member` | 浼氬憳缁村害 | 鐢变細鍛樻。妗?+ 鍗′俊鎭綊骞惰€屾潵 |
+| `dim_member_card_type` | 浼氬憳鍗$被鍨嬬淮搴? | 鍗$/绛夌骇绛夋灇涓剧淮 |
+| `dim_product` | 鍟嗗搧缁村害 | 鍟嗗搧涓绘暟鎹紙鍝佺墝绾э級 |
+| `dim_product_category` | 鍟嗗搧鍒嗙被缁村害 | 浠庡晢鍝佸垎绫婚厤缃?JSON 鏋勫缓 |
+| `dim_table` | 鍙版缁村害 | 鍙板彿銆佸尯鍩熴€佸彴鍨嬬瓑 |
+| `dim_assistant` | 鍔╂暀缁村害 | 鍔╂暀/闄粌璐﹀彿涓绘暟鎹? |
+| `dim_assistant_team` | 鍔╂暀鍥㈤槦缁村害锛堝浣跨敤锛? | 鐝粍/鍥㈤槦淇℃伅 |
+| `dim_pay_method` | 鏀粯鏂瑰紡缁村害 | 鏀粯娓犻亾鏋氫妇锛堢幇閲?寰俊绛夛級 |
+| `dim_order_assist_type`| 鍔╂暀鏈嶅姟绫诲瀷缁村害 | 鍩虹璇?闄勫姞璇剧瓑绫诲瀷 |
+| `dim_coupon_platform` | 鍒稿钩鍙扮淮搴︼紙缇庡洟/鐐硅瘎绛夛級 | 鍥㈣喘鍒告潵婧愭笭閬? |
+| `dim_date` 绛? | 鏃堕棿缁村害 | 鑷劧鏃ョ矑搴︼紝涓嶅仛钀ヤ笟鏃ュ垏鍒? |
+
+**浜嬪疄琛紙Fact锛夛細**
+
+| 琛ㄥ悕 | 绮掑害鎻忚堪 |
+|----------------------------|-------------------------------------------|
+| `fact_sale_item` | 鍟嗗搧閿€鍞槑缁嗭細1 琛?= 1 涓晢鍝侀攢鍞 |
+| `fact_table_usage` | 鍙拌垂浣跨敤鏄庣粏锛? 琛?= 1 绗斿彴妗屼娇鐢ㄨ褰? |
+| `fact_assistant_service` | 鍔╂暀鏈嶅姟鏄庣粏锛? 琛?= 1 鏉″姪鏁欐湇鍔¤褰? |
+| `fact_coupon_usage` | 鍥㈣喘鍒镐娇鐢ㄦ槑缁嗭細1 琛?= 1 娆″埜鏍搁攢 |
+| `fact_payment` | 鏀粯鏄庣粏锛? 琛?= 1 绗旀敮浠樻祦姘? |
+| `fact_refund` | 閫€娆炬槑缁嗭細1 琛?= 1 绗旈€€娆炬祦姘? |
+| `fact_balance_change` | 浣欓鍙樺姩鏄庣粏锛? 琛?= 1 娆′綑棰濆鍑忎簨浠? |
+
+> 璇存槑锛氭湰鏈?DWD 涓嶅啀淇濈暀鈥渟iteProfile鈥濈瓑闂ㄥ簵蹇収瀛楁锛岃€屾槸缁熶竴娌夋穩鍒?`dim_site`锛屾墍鏈変簨瀹炶〃閫氳繃 `site_id` 鍏宠仈闂ㄥ簵銆?
+
+#### 2.1.3 DWS 灞傝〃锛堟眹鎬诲琛級
+
+DWS 灞傞潰鍚戠粡钀ュ垎鏋愬満鏅緭鍑烘眹鎬荤粨鏋滐紝鏈湡閲嶇偣濡備笅锛?
+
+| 琛ㄥ悕 | 绮掑害鎻忚堪 |
+|-------------------------|----------------------------------------------------|
+| `dws_order_summary` | 璁㈠崟姹囨€诲琛細1 琛?= 1 娆$粨璐?/ 鍗曠瑪娑堣垂 |
+| 锛堝悗缁彲鎵╁睍锛? | 锛堟寜鏃?鎸夊姪鏁?鎸夐棬搴楃殑鍚勭被缁忚惀鏃ユ姤銆佺哗鏁堝琛ㄧ瓑锛? |
+
+> 璇存槑锛?
+> - `dws_order_summary` 鏄湰鏈熸渶鏍稿績鐨?DWS 琛紝鎵€鏈夆€滆鍗曟湁鏁堟祦姘淬€佽璐︽祦姘淬€佸彴璐?鍟嗗搧/鍔╂暀鏀跺叆鎷嗚В鈥濈瓑鎸囨爣鍧囧湪姝よ〃瀹氫箟銆?
+> - 鏈湡鏆備笉杈撳嚭鎸夋棩/鎸夊姪鏁欑瓑 DWS 瀹借〃锛屽鍚庣画鏈夐渶姹傦紝鍙熀浜?DWD 鍜?`dws_order_summary` 鍐嶈寤鸿銆?
+2. ODS灞傝〃瀹氫箟锛堟簮鏁版嵁琛級
+ODS灞傜洿鎺ュ瓨鍌ㄤ笟鍔$郴缁熷悇鏁版嵁婧愮殑鏄庣粏璁板綍锛岀粨鏋勪笌婧?JSON 鍩烘湰瀵瑰簲銆備竴鏉DS璁板綍閫氬父瀵瑰簲婧愮郴缁熶腑鐨勪竴鏉′笟鍔¤褰曪紙鎴栦笟鍔″璞″揩鐓э級銆傚瓧娈靛懡鍚嶄互鏉ユ簮瀛楁鑻辨枃涓哄噯锛屾暟鎹被鍨嬭创杩戞簮鏁版嵁绫诲瀷銆傛瘡涓瓧娈靛潎鏍囨敞鏉ユ簮JSON璺緞锛屼究浜嶦TL寮€鍙戝噯纭彇鏁般€備互涓嬫寜鐓т笟鍔′富棰橀€愪竴鍒楀嚭ODS琛ㄨ璁★細
+member_profiles锛堜細鍛樻。妗堣〃锛?
+鎻忚堪锛?瀛樺偍浼氬憳璐︽埛鍩烘湰淇℃伅锛屾瘡鏉¤褰曞搴斾竴涓鎴峰唴鐨勪細鍛樿处鎴凤紙閫氬父涔熷搴斾竴寮犱細鍛樺崱锛夈€傝琛ㄦ槸浼氬憳缁村害鐨勫熀纭€鏁版嵁锛屾彁渚涗細鍛樼殑韬唤鏍囪瘑鍙婅仈绯讳俊鎭瓑銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 浼氬憳璐︽埛ID锛屽敮涓€鏍囪瘑浼氬憳锛堢鎴疯寖鍥村唴锛夈€傛潵婧怞SON璺緞: $.id
+鈥?tenant_id (BIGINT) - 绉熸埛ID锛堝搧鐗孖D锛夈€傚綋鍓嶆暟鎹腑鍥哄畾涓哄崟涓€鍊硷紝浣嗚璁′繚鐣欐瀛楁浠ユ敮鎸佸鍝佺墝銆傛潵婧? $.tenant_id
+鈥?member_name (STRING) - 浼氬憳濮撳悕銆傚浼氬憳鏈疄鍚嶏紝鍙兘涓虹┖鎴栦负榛樿鍊笺€傛潵婧? $.name锛堣嫢JSON鏃犳槑纭畁ame瀛楁锛屽垯浣跨敤鐪熷疄濮撳悕瀛楁锛?
+鈥?nickname (STRING) - 浼氬憳鏄电О銆傝嫢鏃犲崟鐙樀绉板垯鍙兘涓庡鍚嶇浉鍚屾垨鐣欑┖銆傛潵婧? $.nickname
+鈥?mobile (STRING) - 浼氬憳鎵嬫満鍙枫€?1浣嶆墜鏈哄彿鐮佸瓧绗︿覆锛屽敮涓€鏍囪瘑浼氬憳鑱旂郴鏂瑰紡銆傘€愰噸澶嶇殑鎵嬫満鍙峰簲涓烘暟鎹紓甯革紝鍚屼竴鍙风爜閲嶅鍑虹幇闇€鍦‥TL鏃惰€冭檻鍚堝苟鎴栨竻娲椼€戞潵婧? $.mobile
+鈥?gender (STRING) - 浼氬憳鎬у埆銆傛潵婧? $.sex锛堜緥濡?"M"/"F" 鎴栧叾浠栨爣璁帮紝濡侸SON涓烘暟瀛楅渶杞崲涓烘弿杩帮紝鍙湪DWD闃舵鍏宠仈鎬у埆缁磋〃锛?
+鈥?birthday (DATE) - 浼氬憳鐢熸棩銆傛潵婧? $.birthday锛堝婧愪负瀛楃涓查渶杞崲涓烘棩鏈燂級
+鈥?register_time (DATETIME) - 浼氬憳鍏ヤ細鏃堕棿/寮€鎴锋椂闂淬€傛潵婧? $.register_time
+鈥?member_type_id (BIGINT) - 浼氬憳鍗$被鍨婭D銆傝〃绀轰細鍛樻墍鎸佸崱鐨勭被鍨?绾у埆锛屼笌鍗$瀹氫箟鐩稿叧鑱斻€傛潵婧? $.cardTypeId锛堝JSON涓互鍏蜂綋瀛楁鎻愪緵锛?
+鈥?member_type_name (STRING) - 浼氬憳鍗$被鍨嬪悕绉般€傚鈥滈粍閲戝崱鈥濄€佲€滅櫧閾跺崱鈥濈瓑锛屾弿杩颁細鍛樼骇鍒垨鍗$鏉冪泭銆傛潵婧? $.cardTypeName锛堝鏋淛SON涓彁渚涳紱濡傛湭鎻愪緵鍒欓渶鍦―WD浠庡崱鍒楄〃鎴栭厤缃帹瀵硷級
+鈥?status (STRING) - 浼氬憳璐︽埛鐘舵€併€備緥濡傗€滄甯糕€濄€佲€滃仠鐢ㄢ€濈瓑銆傛潵婧? $.status 鎴?$.state锛堟寜JSON瀹為檯瀛楁锛?
+鈥?balance (DECIMAL(10,2)) - 褰撳墠鍌ㄥ€间綑棰濄€傚崟浣嶏細鍏冦€傛潵婧? $.balance锛堝鏋滀細鍛樻。妗圝SON鎻愪緵褰撳墠浣欓锛?
+鈥?points (DECIMAL(10,2)) - 褰撳墠绉垎鎴栫偣鏁般€傚崟浣嶏細鍒嗐€傛潵婧? $.point 鎴?$.points锛堝鏈夛級
+鈥?last_visit_time (DATETIME) - 鏈€杩戜竴娆″埌搴?娑堣垂鏃堕棿銆傛潵婧? $.lastVisitTime锛堝鏈夛級
+鈥?wechat_id (STRING) - 寰俊ID鎴栫粦瀹氱殑寰俊璇嗗埆鐮併€傛潵婧? $.wechatId锛堝鏈夛級
+鈥?alipay_id (STRING) - 鏀粯瀹滻D鎴栫粦瀹氳处鍙枫€傛潵婧? $.alipayId锛堝鏈夛級
+鈥?member_card_no (STRING) - 浼氬憳鍗″彿銆傜敤浜庡疄浣撳崱鍦烘櫙涓嬬殑鍗$墖缂栧彿銆傛潵婧? $.cardNo锛堝鏈夛級
+鈥?remarks (STRING) - 浼氬憳澶囨敞銆傛潵婧? $.remark锛堝鏈夊娉ㄥ瓧娈碉級
+(璇存槑: 鍘熷鈥滀細鍛樻。妗?json鈥濅腑鍑虹幇浜嗕竴渚嬮噸澶嶈褰曪紙鐩稿悓id鐨勮褰曢噸澶嶏級锛孍TL闇€杩囨护姝ょ被閲嶅锛屼互id鍞竴涓哄噯銆備笂杩板瓧娈靛彲鑳藉垎鏁d簬浼氬憳妗f鍜屽偍鍊煎崱鍒楄〃涓や釜婧愶紝鍦∣DS闃舵鏆備互浼氬憳妗fJSON涓哄噯锛屽鏌愪簺瀛楁缂哄け鍙湪DWD闃舵缁撳悎鈥滃偍鍊煎崱鍒楄〃鈥濊ˉ鍏呫€?
+member_stored_value_cards锛堜細鍛樺崱鍒楄〃琛級
+鎻忚堪锛?瀛樺偍浼氬憳鍗″紑鍗¤褰曞強鍗$姸鎬佷俊鎭€傛瘡鏉¤褰曞搴斾竴寮犲凡寮€閫氱殑浼氬憳鍗★紝鍖呭惈鍗$殑瀹氫箟灞炴€у拰褰撳墠鐘舵€併€傚嵆渚垮綋鍓嶇郴缁熶粎鏈夊偍鍊煎崱锛屼篃缁熶竴鎸夊崱鐗囪瑙掕褰曘€?
+瀛楁瀹氫箟锛?
+鈥?card_id (BIGINT) - 浼氬憳鍗″疄渚婭D锛屽敮涓€鏍囪瘑涓€寮犲叿浣撲細鍛樺崱銆傛潵婧怞SON璺緞: $.id锛堝偍鍊煎崱鍒楄〃JSON涓殑鍗$墖涓婚敭锛?
+鈥?member_id (BIGINT) - 鎸佸崱浼氬憳ID銆傚搴擮DS_MEMBER_PROFILE琛ㄧ殑id锛岀敤浜庡叧鑱斾細鍛樺熀鏈俊鎭€傛潵婧? $.member_id 鎴?$.memberCardId锛堟牴鎹疄闄呭瓧娈碉紝濡傚嚭鐜癿ember_card_id搴斿搴斾細鍛樻。妗坕d锛?
+鈥?card_type_id (BIGINT) - 鍗$ID銆傛爣璇嗘鍗″搴旂殑鍗$瀹氫箟锛屼緥濡傚偍鍊煎崱銆佹鍗$瓑绫诲埆銆傛潵婧? $.cardTypeId
+鈥?card_type_name (STRING) - 鍗$鍚嶇О銆傛潵婧? $.cardTypeName锛堜緥濡傗€滃偍鍊煎崱鈥濃€滄鍗♀€濈瓑锛?
+鈥?card_balance (DECIMAL(10,2)) - 鍗″綋鍓嶄綑棰濄€傚崟浣嶏細鍏冦€傛潵婧? $.balance
+鈥?discount_rate (DECIMAL(5,2)) - 鎶樻墸鐜囥€傚鎸佹鍗℃秷璐瑰彲浜彈鐨勬姌鎵o紝90%鍒欏瓨0.90銆傛潵婧? $.discount锛堝瓧娈靛惈涔夐渶纭锛屽彲鑳絁SON涓彁渚涙姌鎵h鍒欙級
+鈥?valid_start_date (DATE) - 鍗℃湁鏁堟湡璧峰鏃ユ湡銆傛潵婧? $.validStart 鎴栫被浼煎瓧娈?
+鈥?valid_end_date (DATE) - 鍗℃湁鏁堟湡鎴鏃ユ湡銆傛潵婧? $.validEnd
+鈥?last_consume_time (DATETIME) - 鏈€杩戜竴娆′娇鐢ㄨ鍗$殑娑堣垂鏃堕棿銆傛潵婧? $.lastConsumeTime
+鈥?status (STRING) - 鍗$姸鎬併€傚鈥滄甯糕€濄€佲€滃凡杩囨湡鈥濄€佲€滃凡鎸傚け鈥濈瓑銆傛潵婧? $.status锛堣嫢涓烘暟瀛椾唬鐮佸皢鍦―WD鍏宠仈缁磋〃锛?
+鈥?activate_time (DATETIME) - 寮€鍗℃椂闂?婵€娲绘椂闂淬€傛潵婧? $.activateTime
+鈥?deactivate_time (DATETIME) - 娉ㄩ攢鏃堕棿锛堝閫傜敤锛夈€傛潵婧? $.cancelTime锛堝鏈夛級
+鈥?issuer_name (STRING) - 寮€鍗℃搷浣滃憳濮撳悕銆傛潵婧? $.issuerName锛堝鏈夛級
+鈥?issuer_id (BIGINT) - 寮€鍗℃搷浣滃憳ID銆傛潵婧? $.issuerId
+(璇存槑: 濡傛灉姣忎釜浼氬憳鍙湁涓€寮犲崱锛孫DS_MEMBER_PROFILE涓嶰DS_MEMBER_CARD璁板綍灏嗕竴涓€瀵瑰簲锛涗絾妯″瀷璁捐浠嶅尯鍒嗕袱琛紝浠ユ敮鎸佷竴浜哄鍗″満鏅€備緥濡傛湭鏉ュ彲鑳芥帹鍑轰笉鍚岀被鍨嬬殑浼氬憳鍗°€佹垨鏃у崱鏇存崲鏂板崱绛夈€侲TL浠庘€滃偍鍊煎崱鍒楄〃.json鈥濇彁鍙栦笂杩板瓧娈点€?
+member_balance_changes锛堜綑棰濆彉鏇磋褰曡〃锛?
+鎻忚堪: 瀛樺偍浼氬憳璐︽埛浣欓姣忔鍙樺姩鐨勬祦姘磋褰曘€傚寘鎷細鍛樺厖鍊笺€佹秷璐规墸娆俱€佸悗鍙拌皟鏁寸瓑瀵艰嚧鍌ㄥ€间綑棰濆鍑忕殑浜嬩欢銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 浣欓鍙樻洿璁板綍ID锛屽敮涓€鏍囪瘑涓€娆′綑棰濆彉鍔ㄤ簨浠躲€傛潵婧怞SON璺緞: $.id
+鈥?member_id (BIGINT) - 浼氬憳璐︽埛ID銆傛湰娆′綑棰濆彉鍔ㄥ叧鑱旂殑浼氬憳锛屽紩鐢∣DS_MEMBER_PROFILE.id銆傛潵婧? $.memberId 鎴?$.member_card_id锛堟牴鎹甁SON瀛楁锛屽鍑虹幇member_card_id鍒欏搴斾細鍛樻。妗坕d锛?
+鈥?change_amount (DECIMAL(10,2)) - 鍙樺姩閲戦銆傛鏁拌〃绀鸿处鎴峰厖鍊?澧炲姞锛岃礋鏁拌〃绀烘秷璐规墸鍑忋€傚崟浣嶏細鍏冦€傛潵婧? $.change_amount锛堣嫢JSON灏嗗厖鍊间笌鎵f缁熶竴姝h礋琛ㄧず锛?
+鈥?balance_before (DECIMAL(10,2)) - 鍙樺姩鍓嶄綑棰濄€傛潵婧? $.before_balance锛堝鏈夛級
+鈥?balance_after (DECIMAL(10,2)) - 鍙樺姩鍚庝綑棰濄€傛潵婧? $.after_balance锛堝鏈夛級
+鈥?change_type (INT) - 鍙樺姩绫诲瀷浠g爜銆傜敤浜庡尯鍒嗕綑棰濆彉鍔ㄥ師鍥?鏉ユ簮锛屼緥濡?=鍏呭€笺€?=娑堣垂銆?=璋冩暣绛夈€傘€愬湪DWD灏嗗叧鑱旂淮琛ㄨ幏鍙栫被鍨嬫弿杩般€戞潵婧? $.from_type 鎴?$.type
+鈥?relate_id (BIGINT) - 鐩稿叧涓氬姟鍗曟嵁ID銆傜敤浜庡叧鑱斾骇鐢熸娆′綑棰濆彉鍔ㄧ殑涓氬姟璁板綍锛屼緥濡傚厖鍊艰褰旾D銆佽鍗曠粨绠桰D銆佸埜鏍搁攢ID绛夈€傝嫢涓?鎴栫┖琛ㄧず鏃犲搴斿崟锛堝绾悗鍙拌皟鏁达級銆傛潵婧? $.relate_id
+鈥?pay_method (INT) - 鏀粯鏂瑰紡浠g爜銆備粎鍦ㄥ厖鍊兼垨娑堣垂閫氳繃鏌愭敮浠樻笭閬撴椂鏈夋剰涔夛紝琛ㄧず姝ゆ鍙樺姩娑夊強鐨勪粯娆炬笭閬擄紙濡傜幇閲戙€佸井淇$瓑锛夈€傛潵婧? $.pay_type锛堝鏋滀綑棰濆彉鍔ㄨ褰曚腑鍖呭惈鏀粯鏂瑰紡淇℃伅锛?
+鈥?remark (STRING) - 澶囨敞淇℃伅銆傚姝ゆ浣欓鍙樻洿鐨勮鏄庢枃瀛椼€傛潵婧? $.remark锛堝鏈夛級
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傛墽琛屾娆′綑棰濆彉鍔ㄦ搷浣滅殑鍛樺伐璐﹀彿銆傛潵婧? $.operatorId
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operatorName
+鈥?change_time (DATETIME) - 鍙樺姩鏃堕棿銆傝褰曚綑棰濆疄闄呭彉鏇村彂鐢熺殑鏃堕棿銆傛潵婧? $.create_time 鎴?$.changeTime
+鈥?tenant_id (BIGINT) - 绉熸埛ID锛堝搧鐗孖D锛夛紝鏉ユ簮: $.tenant_id锛堥€氬父鍥哄畾鍊硷級
+鈥?site_id (BIGINT) - 闂ㄥ簵ID锛屾寚鏄庡彂鐢熸鍙樺姩鐨勯棬搴椼€傛潵婧? $.site_id锛堥€氬父鍥哄畾鍊硷紝浣嗛鐣欏闂ㄥ簵锛?
+鈥?is_deleted (TINYINT) - 璁板綍鏄惁琚垹闄ゆ爣蹇椼€?=姝e父锛?=宸插垹闄わ紙鍙兘鐢ㄤ簬杞垹锛夈€傛潵婧? $.is_delete 鎴?$.is_deleted锛堝鏈夛級
+(璇存槑: 閫氳繃 change_type 鍜?relate_id锛屽彲浠ュ湪DWD灞傝繘涓€姝ュ皢浣欓鍙樺姩涓庡叿浣撲笟鍔′簨瀹烇紙鍏呭€笺€佹秷璐圭粨绠楃瓑锛夊叧鑱旇捣鏉ャ€備緥濡?change_type=鍏呭€兼椂锛宺elate_id瀵瑰簲 ODS_RECHARGE.id锛沜hange_type=娑堣垂鎵f鏃讹紝relate_id瀵瑰簲 settlement_recordsMENT.id 绛夈€?
+ODS_RECHARGE_RECORD锛堝厖鍊艰褰曡〃锛?
+鎻忚堪: 瀛樺偍浼氬憳鍌ㄥ€煎崱鍏呭€肩殑璁板綍銆傛瘡鏉¤褰曡〃绀轰竴绗斾細鍛樺厖鍊硷紙澧炲€硷級浜ゆ槗锛岄€氬父瀵瑰簲浼氬憳鏀粯涓€瀹氶噾棰濆苟澧炲姞璐︽埛浣欓銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍏呭€艰褰旾D锛屽敮涓€鏍囪瘑涓€绗斿厖鍊间氦鏄撱€傛潵婧怞SON璺緞: $.id
+鈥?member_id (BIGINT) - 浼氬憳璐︽埛ID锛屾寚鏄庡厖鍊煎埌璐︾殑浼氬憳銆傛潵婧? $.memberId 鎴?$.member_card_id
+鈥?recharge_amount (DECIMAL(10,2)) - 鍏呭€奸噾棰濄€備細鍛樺疄闄呮敮浠樼殑閲戦銆傚崟浣嶏細鍏冦€傛潵婧? $.amount
+鈥?bonus_amount (DECIMAL(10,2)) - 璧犻€侀噾棰濄€傝嫢鏈夊厖鍊间紭鎯犳椿鍔ㄨ禒閫佺殑棰濆閲戦銆傛潵婧? $.gift_amount 鎴?$.bonus锛堝鏈夛級
+鈥?total_amount (DECIMAL(10,2)) - 鍏呭€兼€婚銆傚嵆鍏呭€奸噾棰?+ 璧犻€侀噾棰濓紝璐︽埛瀹為檯澧炲姞鐨勪綑棰濄€傚崟浣嶏細鍏冦€傛潵婧? 鏃狅紙鍙疎TL璁$畻寰楀埌锛?
+鈥?pay_method (INT) - 鏀粯鏂瑰紡浠g爜銆備細鍛橀€氳繃浣曠娓犻亾鏀粯浜嗘娆″厖鍊奸噾棰濓紝濡?=鐜伴噾銆?=寰俊绛夈€傛潵婧? $.pay_type锛堝JSON鎻愪緵锛?
+鈥?pay_status (INT) - 鏀粯鐘舵€佷唬鐮併€傚0=鏈敮浠橈紝1=宸叉敮浠橈紝2=鏀粯瀹屾垚/鎴愬姛銆傛潵婧? $.pay_status锛堟牱鏈腑鍏呭€间竴鑸洿鎺ユ垚鍔燂級
+鈥?transaction_id (STRING) - 绗笁鏂规敮浠樻祦姘村彿銆傚閫氳繃寰俊/鏀粯瀹濆厖鍊煎搴旂殑鏀粯浜ゆ槗鍙枫€傛潵婧? $.transactionId锛堝鏈夛級
+鈥?recharge_time (DATETIME) - 鍏呭€兼椂闂淬€傛潵婧? $.create_time 鎴?$.rechargeTime
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傛墽琛屾垨鐧昏姝ゆ鍏呭€肩殑宸ヤ綔浜哄憳璐﹀彿銆傛潵婧? $.operatorId
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operatorName
+鈥?tenant_id (BIGINT) - 绉熸埛ID銆傛潵婧? $.tenant_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+(璇存槑: 鍏呭€兼垚鍔熷悗浼氬憳璐︽埛浣欓澧炲姞锛屽搴旂殑浣欓鍙樻洿璁板綍涔熶細鏈変竴鏉′笌涔嬪叧鑱斻€傞€氳繃 pay_method 鍙互鍒嗘瀽浼氬憳鍠滄鐨勫厖鍊兼笭閬撳垎甯冦€?
+ODS_PRODUCT锛堝晢鍝佹。妗堣〃锛?
+鎻忚堪: 瀛樺偍鍝佺墝绾у晢鍝佹。妗堜俊鎭€傛瘡鏉¤褰曞敮涓€鏍囪瘑涓€涓敱鎬婚儴/鍝佺墝瀹氫箟鐨勫晢鍝侊紙鍟嗗搧鍩烘湰淇℃伅锛夛紝涓嶅尯鍒嗗叿浣撻棬搴椼€傚晢鍝佸彲浠ユ槸閰掓按銆佸皬鍚冪瓑鍗栧搧锛屼篃鍙兘鍖呮嫭鏈嶅姟绫婚」鐩紙濡傛寜娆℃敹璐圭殑鏈嶅姟锛夈€?
+瀛楁瀹氫箟锛?
+鈥?goods_id (BIGINT) - 鍟嗗搧ID锛屽晢鍝佹。妗堜富閿紝鍞竴鏍囪瘑涓€涓晢鍝佸畾涔夈€傛潵婧怞SON璺緞: $.id
+鈥?tenant_id (BIGINT) - 绉熸埛ID锛堝搧鐗孖D锛夈€傚悓涓€鍝佺墝鐨勫晢鍝佸湪鍚勯棬搴楀叡浜tenant_id銆傛潵婧? $.tenant_id
+鈥?goods_name (STRING) - 鍟嗗搧鍚嶇О銆傛潵婧? $.name 鎴?$.goodsName
+鈥?goods_code (STRING) - 鍟嗗搧缂栫爜銆傜敤浜庡唴閮ㄧ鐞嗙殑缂栫爜锛屽鏉$爜鎴栬嚜瀹氫箟鐮併€傛潵婧? $.code锛堝鏈夛級
+鈥?goods_type_id (BIGINT) - 鍟嗗搧绫诲埆ID銆傚紩鐢ㄥ晢鍝佸垎绫荤淮搴︼紝渚嬪閰掓按銆佸皬鍚冦€佹湇鍔$瓑绫诲埆銆傛潵婧? $.category_id锛堝鈥滃簱瀛樺彉鍖栬褰?鈥濅腑瀹氫箟鐨勫垎绫籌D锛?
+鈥?goods_type_name (STRING) - 鍟嗗搧绫诲埆鍚嶇О銆傛潵婧? $.category_name锛堝鏈夋彁渚涳級
+鈥?unit (STRING) - 璁¢噺鍗曚綅銆傚鈥滅摱鈥濄€佲€滀唤鈥濄€佲€滃皬鏃垛€濈瓑銆傛潵婧? $.unit
+鈥?price (DECIMAL(10,2)) - 鏍囧噯鍞环銆傚搧鐗屽缓璁浂鍞环銆傛潵婧? $.price
+鈥?cost_price (DECIMAL(10,2)) - 鎴愭湰浠枫€傛潵婧? $.cost_price锛堝鏈夛級
+鈥?is_service (TINYINT) - 鏄惁鏈嶅姟绫婚」鐩爣璇嗐€?琛ㄧず鏈嶅姟锛堝璁℃椂鏀惰垂椤圭洰锛夛紝0琛ㄧず鍟嗗搧銆傛潵婧? $.is_service锛堝鍟嗗搧妗f鍖哄垎浜嗗疄鐗╀笌鏈嶅姟锛?
+鈥?status (STRING) - 鍟嗗搧鐘舵€併€傚鈥滀笂鏋垛€濄€佲€滀笅鏋垛€濄€傛潵婧? $.status锛堣嫢涓烘灇涓剧爜灏嗗湪缁磋〃鏄犲皠锛?
+鈥?created_time (DATETIME) - 鍟嗗搧妗f鍒涘缓鏃堕棿銆傛潵婧? $.create_time
+鈥?updated_time (DATETIME) - 鏈€杩戜慨鏀规椂闂淬€傛潵婧? $.update_time
+(璇存槑: 閮ㄥ垎瀛楁濡傚晢鍝佸垎绫诲彲鑳介渶瑕佷笌鍙︿竴涓狫SON锛堝簱瀛樺彉鍖栬褰?.json锛夌殑鍟嗗搧鍒嗙被鏍戝搴旓紝ODS_PRODUCT涓彲鐩存帴瀛樺垎绫籌D锛屽垎绫诲悕绉板彲鍦ㄧ淮搴﹁〃涓淮鎶や互閬垮厤閲嶅銆傚晢鍝佹。妗堜富瑕佺敤浜庢彁渚涘晢鍝佺殑鏍囧噯淇℃伅銆?
+ODS_STORE_PRODUCT锛堥棬搴楀晢鍝佹。妗堣〃锛?
+鎻忚堪: 瀛樺偍闂ㄥ簵绾у晢鍝侀厤缃紝姣忔潯璁板綍琛ㄧず鏌愰棬搴椾腑鐨勪竴绉嶅晢鍝佸強鍏惰瀹氾紙渚嬪鍞环銆佷笂涓嬫灦鐘舵€佺瓑锛夈€傚涓棬搴楀彲鍚勮嚜鏈変笉鍚岀殑鍟嗗搧鍒楄〃鎴栭厤缃€傛湰娆℃暟鎹敱浜庝粎涓€搴楋紝ODS_STORE_PRODUCT璁板綍鍗充负璇ュ簵鍟嗗搧鏄庣粏銆?
+瀛楁瀹氫箟锛?
+鈥?site_goods_id (BIGINT) - 闂ㄥ簵鍟嗗搧ID锛屽敮涓€鏍囪瘑鏌愰棬搴楃殑涓€鏉″晢鍝佽褰曘€傛潵婧怞SON璺緞: $.id锛堥棬搴楀晢鍝佹。妗圝SON涓殑涓婚敭锛?
+鈥?goods_id (BIGINT) - 鍟嗗搧ID锛堝搧鐗屽晢鍝両D锛夈€傚叧鑱擮DS_PRODUCT.goods_id锛岃〃绀烘闂ㄥ簵鍟嗗搧鎵€灞炵殑鍟嗗搧妗f瀹氫箟銆傛潵婧? $.tenant_goods_id锛堝瓧娈靛惈涔夛細绉熸埛绾у晢鍝両D锛?
+鈥?tenant_id (BIGINT) - 绉熸埛ID銆傛潵婧? $.tenant_id锛堝簲涓嶰DS_PRODUCT淇濇寔涓€鑷达級
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?goods_name (STRING) - 鍟嗗搧鍚嶇О銆傚湪闂ㄥ簵涓殑灞曠ず鍚嶇О锛堥€氬父涓庡搧鐗屽晢鍝佸悕涓€鑷达紝鍙湁缁嗗井宸紓锛夈€傛潵婧? $.goodsName
+鈥?category_id (BIGINT) - 鍟嗗搧鍒嗙被ID銆傛潵婧? $.goodsCategoryId
+鈥?category_name (STRING) - 鍟嗗搧鍒嗙被鍚嶇О銆傛潵婧? $.goodsCategoryName锛堝鏈夛級
+鈥?selling_price (DECIMAL(10,2)) - 闂ㄥ簵鍞崠浠枫€傛搴楀疄闄呴攢鍞鍟嗗搧鐨勫崟浠枫€傛潵婧? $.sellingPrice
+鈥?member_price (DECIMAL(10,2)) - 浼氬憳浠枫€傚瀵逛細鍛樻湁浼樻儬浠峰垯璁板綍锛屽惁鍒欏彲鑳戒笌鍞崠浠风浉鍚屻€傛潵婧? $.memberPrice锛堝鏈夊瓧娈碉級
+鈥?stock_quantity (DECIMAL(10,2)) - 褰撳墠搴撳瓨鏁伴噺銆傛潵婧? $.stock锛堝鏈夊簱瀛樺瓧娈碉級
+鈥?min_stock_alert (DECIMAL) - 搴撳瓨璀︽垝鍊笺€備綆浜庢鏁板彲鑳介渶瑕佽ˉ璐с€傛潵婧? $.minStock锛堝鏈夛級
+鈥?unit (STRING) - 璁¢噺鍗曚綅銆傛潵婧? $.unit锛堝鏈彁渚涘垯缁ф壙ODS_PRODUCT.unit锛?
+鈥?is_weighable (TINYINT) - 鏄惁绉伴噸鍟嗗搧銆?鏄О閲嶅晢鍝侊紙濡傛按鏋滄寜鏂ゅ崠锛夛紝0闈炵О閲嶃€傛潵婧? $.isWeigh锛堝鏈夛級
+鈥?status (STRING) - 涓婃灦鐘舵€併€備緥锛氣€渙n鈥濅笂鏋躲€佲€渙ff鈥濅笅鏋躲€傛潵婧? $.status
+鈥?created_time (DATETIME) - 璁板綍鍒涘缓鏃堕棿銆傛潵婧? $.create_time
+鈥?updated_time (DATETIME) - 璁板綍鏈€杩戜慨鏀规椂闂淬€傛潵婧? $.update_time
+(璇存槑: 闂ㄥ簵鍟嗗搧妗f鍦ㄥ綋鍓嶆暟鎹腑 tenant_id銆乻ite_id 鍥哄畾鍚勪竴鍊硷紝浣嗗湪妯″瀷涓繚鐣欙紝浠ユ敮鎸佸搴楀満鏅笅鍚屼竴鍟嗗搧鍦ㄤ笉鍚屽簵鏈変笉鍚宻ite_goods_id銆傚簱瀛樼浉鍏冲瓧娈靛stock_quantity鍙敤浜庡簱瀛樺垎鏋愶紝浣嗛攢鍞富棰樹腑鍙兘涓嶉噸鐐逛娇鐢ㄣ€傝嫢鏁版嵁涓嶈冻锛屾绫诲瓧娈靛彲浠ヤ繚鐣欎絾鍦‥TL鏃朵负绌恒€?
+ODS_STORE_SALE_ITEM锛堥棬搴楀晢鍝侀攢鍞褰曡〃锛?
+鎻忚堪: 瀛樺偍鍟嗗搧閿€鍞槑缁嗘祦姘达紝姣忔潯璁板綍浠h〃璁㈠崟涓敭鍑虹殑鏌愮鍟嗗搧琛岄」鐩€備篃绉颁负閿€鍞椤圭洰琛ㄣ€備緥濡備竴绗旇鍗曚拱浜?鐡堕ギ鏂欙紝鍒欐湁3鏉″搴旇褰曪紙鎴栦竴鏉¤褰曞惈鏁伴噺3锛夈€傝繖鏄攢鍞簨瀹炵殑缁嗙矑搴︽暟鎹€?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 閿€鍞祦姘碔D锛屽敮涓€鏍囪瘑涓€鏉¢攢鍞槑缁嗚褰曘€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傝〃绀烘閿€鍞墍灞炵殑璁㈠崟鍙凤紝鐢ㄤ簬灏嗗涓槑缁嗗綊灞炲悓涓€璁㈠崟銆傘€愪笉鍚屾ā鍧楅棿璁㈠崟浜ゆ槗鍙风浉鍚岋紝鐢ㄤ簬涓茶仈鍙拌垂銆佸晢鍝併€佸姪鏁欍€佸椁愮瓑娑堣垂鏄庣粏銆戞潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傚搴旂粨璐﹀崟鍙风殑鍐呴儴涓婚敭銆傚鏋滆鍗曞凡缁撶畻锛屽彲鐢ㄤ簬鍏宠仈缁撹处璁板綍鎴栧皬绁ㄨ鎯呫€傛潵婧? $.order_settle_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?site_goods_id (BIGINT) - 闂ㄥ簵鍟嗗搧ID銆傛爣璇嗗崠鍑虹殑鍟嗗搧锛屽叧鑱擮DS_STORE_PRODUCT.site_goods_id鑾峰彇鍟嗗搧淇℃伅銆傛潵婧? $.site_goods_id
+鈥?goods_id (BIGINT) - 鍟嗗搧ID锛堝搧鐗屽晢鍝両D锛夈€傛柟渚跨洿鎺ュ叧鑱斿晢鍝佺淮搴︺€傛潵婧? $.tenant_goods_id锛堥€氬父涓巗ite_goods_id瀵瑰簲鐨勫搧鐗屽晢鍝両D锛?
+鈥?goods_name (STRING) - 鍟嗗搧鍚嶇О銆傞攢鍞褰曚腑鐨勫啑浣欏晢鍝佸悕銆傛潵婧? $.goodsName
+鈥?quantity (DECIMAL(10,2)) - 閿€鍞暟閲忋€傚崠鍑哄晢鍝佺殑鏁伴噺锛堟垨閲嶉噺锛夈€傛潵婧? $.quantity
+鈥?unit_price (DECIMAL(10,2)) - 鍗曚环銆傚晢鍝佸師鏈崟浠凤紝鍙兘涓烘爣鍑嗗敭浠枫€傛潵婧? $.price 鎴?$.unit_price
+鈥?discount_amount (DECIMAL(10,2)) - 鎶樻墸閲戦銆傝鏄庣粏鑾峰緱鐨勬€绘姌鎵e噺鍏嶉锛堜細鍛樻姌鎵f垨鎵嬪伐浼樻儬锛夈€傛鍊艰〃绀轰紭鎯犻噾棰濓紝0琛ㄧず鏃犳姌鎵c€傛潵婧? $.discount_money锛圝SON涓鏈夛級
+鈥?actual_amount (DECIMAL(10,2)) - 瀹炴敹閲戦銆傚嵆姝ゅ晢鍝佽瀹為檯鏀跺彇閲戦 = 鍗曚环*鏁伴噺 - 鎶樻墸閲戦銆傛潵婧? 鏃狅紙ETL璁$畻锛屾垨JSON涓凡鏈夊$.total_fee锛?
+鈥?is_gift (TINYINT) - 鏄惁璧犻€佸搧鏍囪瘑銆?琛ㄧず璇ュ晢鍝佷綔涓鸿禒鍝佹湭璁′环锛?琛ㄧず姝e父閿€鍞€傛潵婧? $.is_gift锛堝鏈夛級
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傜櫥璁?褰曞叆姝ら攢鍞殑鍛樺伐銆傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+鈥?sales_time (DATETIME) - 閿€鍞椂闂淬€備竴鑸彇璁㈠崟鍒涘缓鏃堕棿锛屽浜庡晢鍝佹槑缁嗙瓑鍚屼簬璁㈠崟寮€鍗曟椂闂淬€傛潵婧? $.create_time
+鈥?salesman_user_id (BIGINT) - 鎺ㄩ攢鍛樼敤鎴稩D銆傛寚濡傛湁涓氬姟鍛樻彁鎴愶紝姝ゅ瓧娈佃褰曞叧鑱旂殑閿€鍞汉鍛樿处鍙稩D銆傛潵婧? $.salesman_user_id锛堝鏈夛級
+鈥?salesman_name (STRING) - 鎺ㄩ攢鍛樺鍚嶃€傛潵婧? $.salesman_name锛堝鏈夛級
+鈥?is_refunded (TINYINT) - 鏄惁宸查€€娆炬爣蹇椼€?琛ㄧず璇ラ攢鍞悗缁湁閫€娆炬挙閿€锛?琛ㄧず姝e父銆傛潵婧? $.is_refund 鎴栨牴鎹€€娆捐褰曞湪DWD琛嶇敓銆?
+鈥?remark (STRING) - 澶囨敞銆傚璇ラ攢鍞槑缁嗙殑棰濆璇存槑銆傛潵婧? $.remark锛堝鏈夛級
+(璇存槑: 鍟嗗搧閿€鍞褰曞湪璁㈠崟绾ф眹鎬绘椂浼氭眹鍏ヨ鍗曟€婚銆傝嫢鏈夐€€娆撅紝鍙兘闇€瑕佸湪DWD灞備笌閫€娆句簨瀹炲叧鑱斾互鏍囪瘑宸查€€娆鹃」銆俤iscount_amount瀛楁缁煎悎浜嗕細鍛樻姌鎵e拰鎵嬪伐鎶樿锛岃嫢闇€鍒嗗埆鍒嗘瀽鍙湪DWD闃舵渚濇嵁瑙勫垯鎷嗗垎銆傚綋鍓峅DS鏁版嵁涓?salesm鐩稿叧瀛楁鏍锋湰涓?鎴栫┖锛屽鏃犳帹閿€鍛樺垯鐣欑┖鍗冲彲銆?
+ODS_TABLE_INFO锛堝彴妗屽垪琛ㄨ〃锛?
+鎻忚堪: 瀛樺偍鍙版淇℃伅缁村害锛屾瘡鏉¤褰曚唬琛ㄩ棬搴椾腑鐨勪竴涓彴妗?鍖呭帰銆傛瘮濡傚彴鐞冩銆並TV鍖呮埧銆侀夯灏嗘埧绛夈€傛涓哄吀鍨嬬淮琛紝涓哄悇绫绘祦姘达紙鍙拌垂銆佸姪鏁欑瓑锛夋彁渚涘彴鍙枫€佸尯鍩熺瓑闈欐€佸睘鎬с€?
+瀛楁瀹氫箟锛?
+鈥?site_table_id (BIGINT) - 鍙版ID锛屼富閿紝鍞竴鏍囪瘑涓€涓彴妗屻€傛潵婧怞SON璺緞: $.id
+鈥?tenant_id (BIGINT) - 绉熸埛ID锛堝搧鐗孖D锛夈€傛潵婧? $.tenant_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?table_name (STRING) - 鍙版鍚嶇О/缂栧彿銆備緵涓氬姟灞曠ず鐨勫悕绉帮紝濡傗€淎1鈥濄€佲€淏3鈥濄€佲€淰IP1鈥濄€佲€滄柉1鈥濓紙鏂鍏?鍙锋锛夌瓑銆傛潵婧? $.tableName 鎴栧悎鎴愯嚜鍖哄煙+缂栧彿
+鈥?table_no (STRING) - 鍙版缂栧彿锛堢函鏁板瓧閮ㄥ垎锛夈€傚鏋滄湁鍗曠嫭缂栧彿瀛楁鍒欒褰曪紝娌℃湁鍒欏彲涓巘able_name鐩稿悓銆傛潵婧? $.tableNo锛堝鏈夛級
+鈥?area_id (BIGINT) - 鍙版鍖哄煙ID銆傜敤浜庡尯鍒嗗彴妗屾墍灞炵殑鍖哄煙/鍘咃紝渚嬪A鍖恒€乂IP鍖虹瓑銆傛潵婧? $.tenant_site_region_id 鎴?$.areaId锛堝鏈夛級
+鈥?area_name (STRING) - 鍙版鍖哄煙鍚嶇О銆傚鈥淎鍖衡€濃€淰IP鍘呪€濄€傛潵婧? $.area_name 鎴栭€氳繃鍖哄煙ID鍏宠仈鑾峰緱銆?
+鈥?table_type (STRING) - 鍙版绫诲瀷銆傛爣璇嗘鍙扮敤浜庝綍绉嶉」鐩紝濡傗€滅編寮忓彴鐞冣€濄€佲€滄柉璇哄厠鈥濄€佲€淜TV鍖呮埧鈥濄€佲€滈夯灏嗘埧鈥濈瓑銆傘€愪笉鍐欐鏋氫妇锛孌WD璁捐缁磋〃銆戞潵婧? $.type 鎴栦粠鍚嶇О/閰嶇疆鎺ㄦ柇锛堜緥濡傚悕绉颁腑鈥滄柉鈥濆紑澶磋〃绀烘柉璇哄厠锛?
+鈥?is_vip (TINYINT) - VIP涓撳睘鏍囧織銆?琛ㄧず璇ュ彴涓篤IP涓撶敤锛?琛ㄧず鏅€氥€傛潵婧? 鐢卞悕绉版垨閰嶇疆锛堝鍚嶇О鍖呭惈VIP锛夌‘瀹氾紙鑻ユ簮鏁版嵁鏈夊瓧娈垫洿濂斤級
+鈥?status (STRING) - 鍙版鐘舵€併€傚鈥滃惎鐢ㄢ€濄€佲€滃仠鐢ㄢ€濄€傛潵婧? $.status锛堝鏈夋灇涓撅紝鍦ㄧ淮搴﹁〃鏄犲皠锛?
+鈥?rate (DECIMAL(10,2)) - 鍙拌垂璐圭巼銆傝嫢姣忓彴妗屽彲鑳芥湁涓嶅悓璁¤垂鍗曚环锛堟瘡灏忔椂浠锋牸锛夛紝鍒欒褰曡鍩虹璐圭巼銆傛潵婧? $.rate锛堝鏈夛級
+鈥?description (STRING) - 澶囨敞鎻忚堪銆傚鍙版鐨勯澶栬鏄庯紝濡傚寘鍘㈠ぇ灏忋€佺悆鍙拌鏍肩瓑銆傛潵婧? $.description锛堝鏈夛級
+(璇存槑: 鍙版鍒楄〃閫氬父鐩稿闈欐€侊紝ODS灞備繚瀛樼幇鏈夊彴妗岄厤缃€傝〃涓ず渚嬪€煎鈥滆懀浜嬪姙鈥濄€佲€?66鈥濊〃鏄庨儴鍒嗗彴鍙峰彲浣跨敤鑷畾涔夊懡鍚嶃€俛rea鍜宼ype绛夎嫢鏈湪JSON涓槑纭彁渚涳紝DWD灞傚彲閫氳繃缁存姢缁磋〃鎴栬鍒欒ˉ鍏ㄣ€?
+table_fee_transactions_LOG锛堝彴璐规祦姘磋〃锛?
+鎻忚堪: 璁板綍鍙版浣跨敤锛堣璐癸級娴佹按锛屾瘡鏉¤褰曞搴斾竴绗斿彴妗屼娇鐢ㄦ槑缁嗭紙閫氬父涓庝竴涓鍗曠粦瀹氾級銆傝繖鐩稿綋浜庡浜轰娇鐢ㄤ竴寮犲彴浠庡紑濮嬪埌缁撴潫鎵€浜х敓鐨勫彴璐硅处鍗曘€傚寘鍚璐瑰紑濮嬬粨鏉熸椂闂淬€佹椂闀裤€佸簲鏀惰垂鐢ㄤ互鍙婃姌鎵e噺鍏嶇瓑淇℃伅銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍙拌垂娴佹按ID锛屽敮涓€鏍囪瘑涓€鏉″彴妗屼娇鐢ㄨ褰曘€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛鍙拌垂鎵€灞炶鍗曠殑缂栧彿銆傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傝鍗曠粨璐﹀崟涓婚敭锛岀敤浜庡叧鑱旂粨璐?灏忕エ璇︽儏銆傛潵婧? $.order_settle_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?site_table_id (BIGINT) - 鍙版ID銆傚叧鑱擮DS_TABLE_INFO.site_table_id锛屾爣璇嗗摢寮犲彴浜х敓姝よ垂鐢ㄣ€傛潵婧? $.site_table_id
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傚啑浣欏瓨鍌ㄤ究浜庣洿鎺ユ煡鐪嬨€傛潵婧? $.tableName
+鈥?start_use_time (DATETIME) - 寮€鍙版椂闂淬€傞【瀹㈠紑濮嬩娇鐢ㄨ鍙版鐨勬椂闂淬€傛潵婧? $.start_use_time
+鈥?last_use_time (DATETIME) - 缁撴潫鏃堕棿銆傞【瀹㈢粨鏉熶娇鐢?缁撹处鏃堕棿銆傛潵婧? $.last_use_time
+鈥?use_duration (INT) - 浣跨敤鏃堕暱锛屽崟浣嶇鎴栧垎閽熴€傚彲鐢卞紑濮嬬粨鏉熸椂闂磋绠楀緱鍒帮紝鎴栨簮鏁版嵁鐩存帴鎻愪緵銆傛潵婧? 璁$畻(last_use_time - start_use_time)锛屽JSON涓湁 real_table_use_seconds 鍒欑洿鎺ョ敤銆?
+鈥?billing_unit_price (DECIMAL(10,2)) - 璁¤垂鍗曚环銆備娇鐢ㄦ椂鐨勬敹璐规爣鍑嗭紙姣忓皬鏃?姣忓崐灏忔椂閲戦锛夈€傛潵婧? $.ledger_unit_price锛坙edger鍗曚环锛?
+鈥?billing_count (DECIMAL(10,2)) - 璁¤垂鏁伴噺銆傛寜璁¤垂鍗曚綅绱鐨勬暟閲忋€備緥濡傛寜灏忔椂璁¤垂鐨勬€诲皬鏃舵暟銆傛潵婧? $.ledger_count
+鈥?ledger_amount (DECIMAL(10,2)) - 鍘熷鍙拌垂閲戦銆傛牴鎹椂闀垮拰鍗曚环璁$畻鐨勬湭鎶樻墸璐圭敤銆傛潵婧? $.ledger_amount
+鈥?member_discount_amount (DECIMAL(10,2)) - 浼氬憳鎶樻墸閲戦銆傚洜浼氬憳鍗℃姌鎵e噺鍏嶇殑閲戦銆傛潵婧? $.member_discount_amount
+鈥?coupon_discount_amount (DECIMAL(10,2)) - 鍒告姷鎵i噾棰濄€備娇鐢ㄥ洟璐埜绛変績閿€鎶垫墸鐨勯噾棰濄€傛潵婧? $.coupon_promotion_amount
+鈥?manual_adjust_amount (DECIMAL(10,2)) - 鎵嬪伐璋冩暣閲戦銆傞€氳繃鍙拌垂鎵撴姌娴佹按璁板綍鐨勪汉宸ュ噺鍏嶉噾棰濓紙姝e€艰〃绀哄噺鍏嶄簡澶氬皯閽憋級銆傛潵婧? $.adjust_amount
+鈥?service_fee (DECIMAL(10,2)) - 闄勫姞鏈嶅姟璐广€傝嫢鏈夐澶栨湇鍔¤垂锛堜緥濡傚鍦烘湇鍔¤垂锛夎鍏ュ彴璐广€傛潵婧? $.mgmt_fee锛堝瓧娈垫剰涔夋帹娴嬶紝鏍锋湰涓鏈夐潪0鍊煎垯琛ㄧず闄勫姞璐癸級
+鈥?final_table_fee (DECIMAL(10,2)) - 鍙拌垂瀹炴敹閲戦銆傚嵆椤惧鏈€缁堜负璇ュ彴鏀粯鐨勮垂鐢?= ledger_amount - 鎵€鏈夋姌鎵e噺鍏?+ 闄勫姞璐广€傛潵婧? $.real_table_charge_money锛堝JSON鎻愪緵锛涘惁鍒橢TL璁$畻锛?
+鈥?member_id (BIGINT) - 浼氬憳ID銆傝嫢璇ユ寮€鍙扮粦瀹氫簡浼氬憳锛屽垯璁板綍浼氬憳璐︽埛ID锛屽惁鍒欎负绌恒€傛潵婧? $.member_id
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傚姙鐞嗗紑鍙?缁撹处鐨勫憳宸ヨ处鍙枫€傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+鈥?salesman_user_id (BIGINT) - 閿€鍞憳ID銆傛瘮濡傜悆鍙版湇鍔¤繃绋嬩腑鐨勮窡鍗曞憳/钀ラ攢鍛樸€傛潵婧? $.salesman_user_id
+鈥?salesman_name (STRING) - 閿€鍞憳濮撳悕銆傛潵婧? $.salesman_name
+鈥?is_single_order (TINYINT) - 鏄惁鍗曠嫭璁㈠崟鏍囧織銆?琛ㄧず姝ゅ彴浠呰璁㈠崟浣跨敤锛?琛ㄧず鍙兘鏈夎鍗曟媶鍒嗭紙鏋佸皯鎯呭喌锛夈€傛潵婧? $.is_single_order
+鈥?is_deleted (TINYINT) - 璁板綍鍒犻櫎鏍囧織銆?琛ㄧず璇ヨ褰曡浣滃簾锛堜緥濡傝鍗曞彇娑堬級锛?姝e父銆傛潵婧? $.is_delete
+(璇存槑: 鍙拌垂娴佹按琛ㄨ缁嗚褰曟瘡绗斿彴妗屼娇鐢ㄨ处鐩紝鍖呭惈鍚勭鎶樻墸鎷嗗垎锛孍TL鏃跺簲灏介噺淇濈暀杩欎簺瀛楁銆傚湪DWD姹囨€昏鍗曟椂锛宖inal_table_fee姹囨€昏繘鍏ヨ鍗曟€婚噾棰濓紱鍚勭被鎶樻墸棰濅篃鍙眹鎬荤粺璁°€俶anual_adjust_amount瀛楁瀵瑰簲鍙拌垂鎵撴姌璁板綍涓殑鎿嶄綔锛屽鏋滀负0琛ㄧず鏈仛浜哄伐鍑忓厤銆?
+ODS_TABLE_FEE_ADJUST锛堝彴璐规墦鎶樿褰曡〃锛?
+鎻忚堪: 璁板綍閽堝鍙拌垂璐﹀崟鐨勪汉宸ヨ皟鏁达紙鎵撴姌鎴栧噺鍏嶈垂鐢級琛屼负銆傛瘡鏉¤褰曡〃绀轰竴娆″鏌愯鍗曞彴璐圭殑鎵嬪伐鍑忓厤鎿嶄綔锛屽苟闈炲彴鐨勪娇鐢ㄨ褰曟湰韬紝鑰屾槸闄勫姞鐨勪竴鏉¤皟鏁存祦姘淬€傞€氬父鐢ㄤ簬璁板綍鏀堕摱鍛樼粰浜堥【瀹㈢殑鍙拌垂鎶樻墸銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍙拌垂璋冩暣璁板綍ID锛屽敮涓€鏍囪瘑涓€娆″彴璐规墦鎶樻搷浣溿€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛湰璋冩暣鎵€灞炵殑璁㈠崟銆傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傛湰璋冩暣鎵€灞炶鍗曠殑缁撶畻鍗旾D銆傛潵婧? $.order_settle_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id锛堝彲鑳介€氳繃siteProfile鑾峰彇锛?
+鈥?site_table_id (BIGINT) - 鍙版ID銆傛寚鏄庢娆¤皟鏁撮拡瀵瑰摢寮犲彴妗岀殑璐圭敤銆傛潵婧? $.site_table_id锛堝JSON鎻愪緵锛?
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傛潵婧? $.tableName
+鈥?adjust_amount (DECIMAL(10,2)) - 鍑忓厤閲戦銆傛鍊艰〃绀哄噺鍏嶄簡澶氬皯閽憋紙鍗冲彴璐归檷浣庨锛夈€傛潵婧? $.adjust_fee 鎴?$.reduce_amount锛堟寜瀹為檯瀛楁锛?
+鈥?reason (STRING) - 鎵撴姌鍘熷洜銆傚鏈浜哄伐璋冩暣鐨勮鏄庯紝濡傗€滀細鍛樻姇璇夎ˉ鍋库€濇垨鈥滃簵闀跨壒鎵光€濄€傛潵婧? $.reason锛堝鏈夛級
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傛墽琛屾鎵撴姌鎿嶄綔鐨勫憳宸ヨ处鍙枫€傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+鈥?adjust_time (DATETIME) - 璋冩暣鏃堕棿銆傛潵婧? $.create_time
+(璇存槑: 鍙拌垂鎵撴姌璁板綍鍦∣DS_TABLE_USE_LOG涓凡鍙嶆槧涓簃anual_adjust_amount锛屼絾涓轰簡淇濈暀鎿嶄綔鍘熷洜銆佺粡鍔炰汉绛夌粏鑺傦紝ODS浠嶅瓨姝よ〃銆侱WD寤烘ā鏃讹紝鍙皢adjust_amount鍚堝苟璁″叆鍙拌垂鏈€缁堥噾棰濊绠椼€俽eason瀛楁鑻ヤ负鏈夐檺鏋氫妇锛屽彲寤虹珛缁磋〃缁存姢鍚勭鎶樻墸鍘熷洜銆?
+assistant_accounts_master锛堝姪鏁欒处鍙疯〃锛?
+鎻忚堪: 瀛樺偍闂ㄥ簵涓嬫墍鏈夊姪鏁欙紙鏁欑粌/鏈嶅姟浜哄憳锛屽寘鎷鐞嗚处鍙凤級鐨勫熀纭€閰嶇疆鍜屾。妗堜俊鎭€傛瘡鏉¤褰曞搴斾竴鍚嶅姪鏁欒处鍙凤紝灞炰簬浜轰簨缁村害琛ㄣ€傚瓧娈垫兜鐩栧姪鏁欑殑涓汉淇℃伅銆佽处鍙风姸鎬併€佽璐圭瓥鐣ョ瓑銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍔╂暀璐﹀彿ID锛屼富閿€傚敮涓€鏍囪瘑涓€涓姪鏁?鍛樺伐璐﹀彿銆傚湪鍔╂暀鏈嶅姟娴佹按绛変簨瀹炶〃涓互site_assistant_id寮曠敤璇D鍏宠仈銆傛潵婧怞SON璺緞: $.id
+鈥?user_id (BIGINT) - 绯荤粺鐢ㄦ埛ID銆傚姪鏁欒处鍙峰搴旂殑绯荤粺鐧诲綍璐﹀彿ID锛岀敤浜庡湪涓嶅悓妯″潡涓嬬粺涓€璇嗗埆浜哄憳銆傚尯鍒簬宀椾綅绾х殑id銆傛潵婧? $.user_id
+鈥?assistant_no (STRING) - 鍔╂暀宸ュ彿/缂栧彿銆傜敤浜庝笟鍔¤瘑鍒殑缂栧彿锛屽彲鑳戒笉鍞竴锛堜笉鍚屽姪鏁欏彲鑳界紪鍙风浉鍚屼絾id涓嶅悓锛夈€傛潵婧? $.assistantNo
+鈥?job_num (STRING) - 鍔╂暀宸ヤ綔璇佺紪鍙枫€傚鐢ㄥ伐鍙峰瓧娈碉紝褰撳墠闂ㄥ簵鍙兘鏈娇鐢ㄣ€傛潵婧? $.job_num
+鈥?serial_number (INT) - 搴忓彿銆傜郴缁熷唴閮ㄧ敓鎴愮殑鎺掑簭鍙锋垨杩佺Щ鐢ㄧ殑搴忓垪鍊笺€傛潵婧? $.serial_number
+鈥?real_name (STRING) - 鍔╂暀鐪熷疄濮撳悕銆傛潵婧? $.real_name
+鈥?nickname (STRING) - 鍔╂暀鏄电О銆傚墠鍙板睍绀虹敤鐨勭话鍙凤紝渚嬪鈥滀匠鎬♀€濄€佲€滃懆鍛ㄢ€濄€傛潵婧? $.nickname
+鈥?gender (STRING) - 鎬у埆銆傛潵婧? $.sex锛堜緥濡傗€淢鈥?鈥淔鈥濇垨鈥滅敺鈥?鈥滃コ鈥濓級
+鈥?birthday (DATE) - 鍑虹敓鏃ユ湡銆傛潵婧? $.birthday
+鈥?mobile (STRING) - 鎵嬫満鍙枫€傚姪鏁欒仈绯绘墜鏈恒€傛潵婧? $.mobile
+鈥?id_card (STRING) - 韬唤璇佸彿銆傛潵婧? $.id_card锛堝鏈夛級
+鈥?hire_date (DATE) - 鍏ヨ亴鏃ユ湡銆傛潵婧? $.hire_date锛堝鏈夊瓧娈碉級
+鈥?resign_date (DATE) - 绂昏亴鏃ユ湡銆傚璐﹀彿宸插簾闄ゅ垯璁板綍绂昏亴鏃堕棿銆傛潵婧? $.resign_date锛堝鏈夛級
+鈥?status (STRING) - 鍦ㄨ亴鐘舵€併€傜ず渚嬶細鈥滃湪鑱屸€濄€佲€滅鑱屸€濄€佲€滃仠鐢ㄢ€濈瓑銆傛潵婧? $.status锛堣嫢婧愪负鏁板瓧锛屽湪缁磋〃鏄犲皠锛?
+鈥?visible (TINYINT) - 鍓嶅彴鍙鎬с€?琛ㄧず涓嶅湪鍓嶅彴灞曠ず锛?琛ㄧず鍙椤惧鐪嬪埌閫夋嫨銆傛潵婧? $.visible锛堝鏈夛級
+鈥?billing_mode (STRING) - 璁¤垂绛栫暐銆傚姪鏁欐湇鍔¤璐规柟寮忥紝濡傗€滄寜灏忔椂璁¤垂鈥濇垨鍥哄畾鍦烘銆傛潵婧? $.billing_mode锛堟帹娴嬪瓧娈碉紝濡傛棤鏄庣‘鍒欏彲鑳介€氳繃鍏宠仈閰嶇疆鍐冲畾锛?
+鈥?skill_name (STRING) - 鏈嶅姟鎶€鑳藉悕绉般€備緥濡傗€滃熀纭€璇锯€濃€滈檮鍔犺鈥濈瓑锛岃〃绀鸿鍔╂暀鎻愪緵鏈嶅姟鐨勭被鍒€傛潵婧? $.skillName
+鈥?skill_level (STRING) - 鎶€鑳界骇鍒?绛夌骇銆傚鈥滃垵绾р€濃€滈珮绾р€濄€傛潵婧? $.levelName 鎴?$.assistant_level
+鈥?team_id (BIGINT) - 鍔╂暀鍥㈤槦ID銆傚皢鍔╂暀鍒嗙粍鐨勫洟闃?鐝粍鏍囪瘑銆傛潵婧? $.assistant_team_id
+鈥?team_name (STRING) - 鍔╂暀鍥㈤槦鍚嶇О銆傛潵婧? $.ledger_group_name锛堢寽娴嬪搴斿洟闃熷悕绉板瓧娈碉級
+鈥?service_rate (DECIMAL(10,2)) - 鏈嶅姟璐规爣鍑嗐€傚姪鏁欐湇鍔$殑璐圭巼鎴栨彁鎴愭爣鍑嗐€傛潵婧? $.service_rate锛堝鏈夛級
+鈥?comment (STRING) - 澶囨敞銆傚叾浠栬ˉ鍏呰鏄庛€傛潵婧? $.remark锛堝鏈夛級
+鈥?tenant_id (BIGINT) - 绉熸埛ID銆傛潵婧? $.tenant_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+(璇存槑: 鍔╂暀璐﹀彿浣滀负缁磋〃锛屽皢閫氳繃id鎴杣ser_id鍏宠仈鍒板姪鏁欐湇鍔℃祦姘淬€佸姪鏁欐帓鐝瓑浜嬪疄銆傚湪褰撳墠鏁版嵁涓寘鍚鐞嗙被璐﹀彿锛寁isible瀛楁鐢ㄤ簬鎺у埗鍏舵槸鍚︽彁渚涚粰椤惧閫夋嫨鏈嶅姟銆俠illing_mode/skill绛夊喅瀹氬叾鏈嶅姟璁¤垂绫诲埆锛屼緥濡傚尯鍒嗗熀纭€璇惧拰闄勫姞璇撅紝鍦ㄥ姪鏁欐祦姘翠腑涔熸湁瀵瑰簲鏋氫妇鍊笺€?
+ODS_ASSISTANT_SERVICE_LOG锛堝姪鏁欐祦姘磋〃锛?
+鎻忚堪: 璁板綍鍔╂暀鏈嶅姟/闄粌鐨勬槑缁嗘祦姘达紝姣忔潯璁板綍浠h〃涓€娆″姪鏁欎负椤惧鎻愪緵鏈嶅姟鐨勮繃绋嬶紝閫氬父瀵瑰簲璁㈠崟涓殑涓€椤瑰姪鏁欐湇鍔℃秷璐广€傚彲鑳藉寘鍚紑濮嬬粨鏉熸椂闂淬€佹湇鍔¤垂鐢ㄣ€佸姪鏁欒瘎浠风瓑銆傝嫢涓€娆¤鍗曚腑鏇存崲鎴栧娆¤仒璇峰姪鏁欙紝浼氫骇鐢熷鏉¤褰曘€?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍔╂暀娴佹按ID锛屽敮涓€鏍囪瘑涓€鏉″姪鏁欐湇鍔¤褰曘€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛爣璇嗘鍔╂暀鏈嶅姟鎵€灞炵殑璁㈠崟銆傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傚叧鑱旂粨璐﹀崟锛岀敤浜庝笌灏忕エ璇︽儏绛夊搴斻€傘€愬綋鍓嶅鍑虹粨璐﹁褰曚负绌猴紝姝ゅ瓧娈典緷鐒朵繚鐣欑敤浜庡叧鑱斻€戞潵婧? $.order_settle_id
+鈥?order_assistant_id (BIGINT) - 璁㈠崟鍔╂暀椤笽D銆傜敤浜庡尯鍒嗗悓涓€璁㈠崟涓鏉″姪鏁欐湇鍔¢」鐨勫唴閮↖D銆傛潵婧? $.order_assistant_id
+鈥?order_assistant_type (INT) - 鍔╂暀鏈嶅姟绫诲瀷缂栫爜銆傛灇涓惧€硷紝绀轰緥锛?=甯歌鍔╂暀鏈嶅姟锛堝熀纭€璇撅級锛?=闄勫姞鍔╂暀鏈嶅姟锛堝姞璇撅級銆傚搴旂殑鍚箟鍙粠绯荤粺閰嶇疆鑾峰彇銆傘€愭ā鍨嬩腑閫氳繃缁磋〃瑙f瀽銆戞潵婧? $.order_assistant_type
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?site_table_id (BIGINT) - 鍙版ID銆傚姪鏁欐湇鍔℃墍鍦ㄧ殑鍙版锛屽鏁欑粌鍦ㄥ摢寮犵悆鍙版湇鍔°€傛潵婧? $.site_table_id
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傛潵婧? $.tableName
+鈥?site_assistant_id (BIGINT) - 鍔╂暀ID銆傛彁渚涙湇鍔$殑鍔╂暀璐﹀彿ID锛屽叧鑱擮DS_ASSISTANT_ACCOUNT.id銆傛潵婧? $.site_assistant_id
+鈥?assistant_name (STRING) - 鍔╂暀濮撳悕銆傚啑浣欏瓧娈碉紝鏉ユ簮: $.assistantName
+鈥?assistant_no (STRING) - 鍔╂暀宸ュ彿銆傛潵婧? $.assistantNo
+鈥?skill_name (STRING) - 鏈嶅姟鎶€鑳藉悕绉般€備緥锛氣€滃熀纭€璇锯€濇垨鈥滈檮鍔犺鈥濓紝涓巓rder_assistant_type鐩稿搴斻€傛潵婧? $.skillName
+鈥?assistant_level (STRING) - 鍔╂暀绛夌骇/绾у埆銆傚鈥滃垵绾р€濃€滀腑绾р€濄€傛潵婧? $.assistant_level 鎴?$.levelName
+鈥?start_time (DATETIME) - 鏈嶅姟寮€濮嬫椂闂淬€傛潵婧? $.start_use_time
+鈥?end_time (DATETIME) - 鏈嶅姟缁撴潫鏃堕棿銆傛潵婧? $.last_use_time
+鈥?service_duration (INT) - 鏈嶅姟鏃堕暱锛堢锛夈€傛潵婧? $.income_seconds 鎴?$.real_use_seconds锛堝鏈夛級
+鈥?ledger_unit_price (DECIMAL(10,2)) - 璁¤垂鍗曚环銆傚姪鏁欐湇鍔¤垂鐜囷紙姣忓崟浣嶆椂闂磋垂鐢級銆傛潵婧? $.ledger_unit_price
+鈥?ledger_amount (DECIMAL(10,2)) - 鍘熷鏈嶅姟閲戦銆傛寜鏃堕暱鍜屽崟浠疯绠楃殑璐圭敤銆傛潵婧? $.ledger_amount
+鈥?member_discount_amount (DECIMAL(10,2)) - 浼氬憳鎶樻墸閲戦銆備細鍛樹环浼樻儬鐨勯噾棰濄€傛潵婧? $.member_discount_amount
+鈥?coupon_deduct_amount (DECIMAL(10,2)) - 鍒告姷鎵i噾棰濄€備娇鐢ㄤ績閿€鍒告姷鎵g殑閲戦銆傛潵婧? $.coupon_deduct_money
+鈥?manual_discount_amount (DECIMAL(10,2)) - 鎵嬪伐鍑忓厤閲戦銆備汉宸ョ粰浜堢殑鍑忓厤璐圭敤銆傛潵婧? $.manual_discount_amount
+鈥?final_service_fee (DECIMAL(10,2)) - 鍔╂暀鏈嶅姟瀹炴敹閲戦銆? ledger_amount - 鎶樻墸 - 鍒告姷鎵?- 鎵嬪伐鍑忓厤銆傛潵婧? $.service_money锛堟垨ETL璁$畻锛?
+鈥?member_id (BIGINT) - 浼氬憳ID銆傝嫢椤惧涓轰細鍛橈紝姝ゆ湇鍔$粦瀹氱殑浼氬憳璐﹀彿銆傛潵婧? $.tenant_member_id 鎴?$.member_id锛堟牴鎹瓧娈碉紝鏍锋湰涓彲鑳藉瓨鍦╯ystem_member_id/tenant_member_id鐢ㄤ簬鍖哄埆鍝佺墝浼氬憳锛?
+鈥?is_confirm (TINYINT) - 椤惧纭鏍囧織銆?琛ㄧず椤惧宸茬‘璁ゆ湇鍔★紙鍙兘鏈夌瀛楃‘璁ゆ祦绋嬶級锛?鏈‘璁ゃ€傛潵婧? $.is_confirm
+鈥?grade_status (TINYINT) - 璇勫垎鐘舵€併€傛爣璇嗛【瀹㈡槸鍚﹀凡瀵规湰娆℃湇鍔¤瘎鍒?璇勪环銆傛潵婧? $.grade_status
+鈥?service_grade (INT) - 鏈嶅姟鎬佸害璇勫垎銆傚彲鑳借寖鍥?-5銆傛潵婧? $.service_grade锛堝鏈夎瘎鍒嗗姛鑳斤級
+鈥?skill_grade (INT) - 鎶€鑳戒笓涓氬害璇勫垎銆傛潵婧? $.skill_grade
+鈥?sum_grade (INT) - 缁煎悎璇勫垎銆傚彲鑳芥槸骞冲潎鎴栨€诲垎銆傛潵婧? $.composite_grade
+鈥?grade_time (DATETIME) - 璇勪环鏃堕棿銆傛潵婧? $.composite_grade_time
+鈥?get_grade_times (INT) - 鑾疯瘎娆℃暟銆備篃璁歌〃绀鸿鍔╂暀琚瘎浠风殑鎬绘鏁帮紙瀛楁鎰忎箟瀛樼枒锛夈€傛潵婧? $.get_grade_times
+鈥?is_not_responding (TINYINT) - 鍔╂暀鏈搷搴旀爣蹇椼€?琛ㄧず鍔╂暀鏈強鏃跺簲绛旀湇鍔¤姹傘€傛潵婧? $.is_not_responding
+鈥?is_trash (TINYINT) - 浣滃簾鏍囧織銆?琛ㄧず璇ユ湇鍔¤褰曡搴熷純锛堝彲鑳界敱浜庡姪鏁欐洿鎹?鍙栨秷锛夛紝0姝e父銆傛潵婧? $.is_trash
+鈥?trash_reason (STRING) - 搴熼櫎鍘熷洜銆傝嫢is_trash=1锛岃褰曞彇娑堟湇鍔$殑鍘熷洜璇存槑銆傛潵婧? $.trash_reason
+鈥?trash_applicant_id (BIGINT) - 搴熼櫎鐢宠浜篒D銆傝皝鍙戣捣浜嗗彇娑堬紙椤惧鎴栧憳宸ワ級銆傛潵婧? $.trash_applicant_id
+鈥?trash_applicant_name (STRING) - 搴熼櫎鐢宠浜哄鍚嶃€傛潵婧? $.trash_applicant_name
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傜櫥璁版鏈嶅姟鐨勬搷浣滃憳璐﹀彿銆傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+鈥?salesman_user_id (BIGINT) - 閿€鍞憳/鎺ㄤ粙浜篒D銆傚鏈変笟鍔″憳鎺ㄨ崘姝ゆ湇鍔★紝鍒欒褰曘€傛潵婧? $.salesman_user_id
+鈥?salesman_name (STRING) - 閿€鍞憳濮撳悕銆傛潵婧? $.salesman_name
+鈥?remark (STRING) - 澶囨敞銆傞澶栬鏄庛€傛潵婧? $.remark锛堝鏈夛級
+(璇存槑: 鍔╂暀鏈嶅姟娴佹按鍖呭惈涓€浜涙湇鍔¤川閲忕浉鍏冲瓧娈碉紙璇勫垎绛夛級锛岃繖鏄秴鍑虹函娑堣垂璁¤垂鐨勫唴瀹癸紝鍙緵浜哄憳缁╂晥鍒嗘瀽銆俰s_trash=1琛ㄧず璇ヨ褰曞搴斾竴娆″姪鏁欐湇鍔¤鍙栨秷鎴栧簾闄わ紝涓庡姪鏁欏簾闄よ〃鐨勬暟鎹浉鍏炽€倀rash_reason绛夋彁渚涘彇娑堝師鍥犮€傚湪DWD灞傚彲缁撳悎鍔╂暀搴熼櫎璁板綍杩涗竴姝ュ垎鏋愩€?
+
+璁¤垂涓庡簾闄よ涔夎鏄庯紙鏂板锛?
+鍔╂暀娴佹按璁板綍涓秹鍙婁互涓嬩笌璁¤垂鍜屽簾闄ょ浉鍏崇殑鏃堕棿涓庨噾棰濆瓧娈碉紙瀛楁鍚嶄互 JSON / ODS 瀹為檯瀛楁涓哄噯锛夛細
+鈥?real_use_seconds锛氭湰娆″姪鏁欐湇鍔″疄闄呭彂鐢熺殑鏈嶅姟鏃堕暱锛屽崟浣嶇銆?
+鈥?income_seconds锛氭湰娆″姪鏁欐湇鍔′腑锛屽彲璁″叆鏀跺叆鐨勬湇鍔℃椂闀匡紝鍗曚綅绉掋€?
+o 褰撴湇鍔℃甯稿畬鎴愭椂锛岄€氬父 income_seconds = real_use_seconds銆?
+o 褰撴湇鍔′腑閫旇搴熼櫎鏃讹紝鍙兘鍙鍏朵腑涓€閮ㄥ垎鏃堕棿璁¤垂锛屾鏃?income_seconds <= real_use_seconds銆?
+鈥?ledger_amount锛堟垨绫讳技瀛楁锛夛細鎸夎鍒掓湇鍔℃椂闀夸笌璐圭巼璁$畻寰楀埌鐨勫師濮嬪簲鏀堕噾棰濓紙涓嶈€冭檻搴熼櫎锛夈€?
+鈥?projected_income锛堟垨 service_money 绛夛級锛氭湰鏉″姪鏁欐湇鍔℃渶缁堣鍏ヨ惀鏀剁殑閲戦锛屽凡鑰冭檻浼氬憳鎶樻墸銆佹墜宸ュ噺鍏嶄互鍙婂簾闄ら€昏緫銆?
+鈥?is_trash锛氬姪鏁欐祦姘存槸鍚﹁搴熼櫎鐨勬爣璁般€?
+o is_trash = 0 琛ㄧず姝e父瀹屾垚鐨勬湇鍔°€?
+o is_trash = 1 琛ㄧず璇ユ潯鍔╂暀鏈嶅姟琚簾闄わ紙鍙兘鏄湭寮€濮嬪氨搴熼櫎锛屾垨鑰呬腑閫斿簾闄わ級銆?
+搴熼櫎閫昏緫鍦?ODS 灞傜殑璇箟绾﹀畾濡備笅锛?
+1. 鏈疄闄呭彂鐢熸湇鍔$殑搴熼櫎锛?
+o 鎯呭喌锛氶【瀹㈢偣浜嗗姪鏁欙紝浣嗗姪鏁欏皻鏈湡姝f湇鍔★紙渚嬪椹笂鎾ゅ洖锛夈€?
+o 琛ㄥ緛锛歳eal_use_seconds = 0锛宨ncome_seconds = 0锛宲rojected_income = 0锛宨s_trash = 1銆?
+o 鍙e緞锛氳鏉¤褰曚笉浜х敓浠讳綍鏀跺叆锛屼粎浣滀负涓氬姟娴佺▼璁板綍瀛樺湪銆?
+2. 宸查儴鍒嗘湇鍔″悗搴熼櫎锛?
+o 鎯呭喌锛氬姪鏁欐湇鍔′簡涓€娈垫椂闂村悗琚【瀹㈡垨闂ㄥ簵搴熼櫎锛屼緥濡傛湇鍔?100 鍒嗛挓锛屽彧鎸?60 鍒嗛挓璁¤垂銆?
+o 琛ㄥ緛锛歳eal_use_seconds > income_seconds >= 0锛宨s_trash = 1銆?
+o 鍙e緞锛?
+飩?宸茶璐归儴鍒嗭細income_seconds 瀵瑰簲鐨勯噾棰濊鍏?projected_income锛岃涓烘湁鏁堣惀鏀躲€?
+飩?鏈璐归儴鍒嗭細real_use_seconds - income_seconds 瀵瑰簲鐨勬椂闂翠笉璁″叆钀ユ敹锛屼粎浣滀负鏈嶅姟杩囩▼淇℃伅銆?
+3. 姝e父瀹屾垚鐨勬湇鍔★細
+o 鎯呭喌锛氬姪鏁欐湇鍔℃寜璁″垝姝e父瀹屾垚銆?
+o 琛ㄥ緛锛歩s_trash = 0锛岄€氬父 income_seconds = real_use_seconds銆?
+o 鍙e緞锛氭寜 projected_income 鍏ㄩ璁″叆钀ユ敹銆?
+鍚庣画鍦?DWD / DWS 灞傚叧浜庘€滃姪鏁欐敹鍏モ€濈浉鍏虫寚鏍囷紝缁熶竴浠?projected_income锛堟垨鐩稿簲鐨勫疄鏀堕噾棰濆瓧娈碉級涓哄噯锛屽苟缁撳悎 is_trash銆乮ncome_seconds 涓?real_use_seconds 鍋氬彛寰勬帶鍒讹紝閬垮厤鎶婃湭璁¤垂閮ㄥ垎璇畻鍏ヨ惀涓氭敹鍏ャ€?
+
+
+ODS_ASSISTANT_CANCEL_LOG锛堝姪鏁欏簾闄よ褰曡〃锛?
+鎻忚堪: 璁板綍鍔╂暀鏈嶅姟琚彇娑?搴熼櫎鐨勪簨浠躲€傛瘡鏉¤褰曞搴斾竴娆″姪鏁欐湇鍔℃湭瀹屾垚鐨勬儏鍐碉紙渚嬪椤惧瑕佹眰鏇存崲鍔╂暀鎴栨彁鍓嶇粨鏉熸湇鍔★級銆傝繖浜涜褰曢€氬父涓庡姪鏁欐湇鍔℃祦姘寸殑is_trash鏍囧織瀵瑰簲锛岀敤浜庤缁嗘弿杩板簾闄ゅ師鍥犲拰杩囩▼銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍔╂暀搴熼櫎璁板綍ID锛屽敮涓€鏍囪瘑涓€娆″姪鏁欐湇鍔″彇娑堜簨浠躲€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傝鍙栨秷鏈嶅姟鎵€鍦ㄨ鍗曠殑缂栧彿銆傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傛潵婧? $.order_settle_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.siteProfile.id锛堥€氳繃siteProfile瀵硅薄鑾峰彇锛?
+鈥?site_table_id (BIGINT) - 鍙版ID銆傛娆℃秹鍙婄殑鍙版銆傛潵婧? $.site_table_id
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傛潵婧? $.tableName
+鈥?site_assistant_id (BIGINT) - 鍔╂暀ID銆傝鍙栨秷鐨勫姪鏁欒处鍙枫€傛潵婧? $.site_assistant_id
+鈥?assistant_name (STRING) - 鍔╂暀濮撳悕銆傛潵婧? $.assistantName
+鈥?assistant_no (STRING) - 鍔╂暀宸ュ彿銆傛潵婧? $.assistantNo
+鈥?cancel_time (DATETIME) - 搴熼櫎鏃堕棿銆傝褰曟湇鍔¤鍙栨秷鐨勬椂闂淬€傛潵婧? $.create_time锛堟帹娴嬩负璁板綍鍒涘缓鏃堕棿锛?
+鈥?cancel_reason (STRING) - 搴熼櫎鍘熷洜鎻忚堪銆傚鈥滈【瀹笉婊℃剰鈥濄€佲€滆秴鏃舵湭鍝嶅簲鈥濈瓑銆傛潵婧? $.reason 鎴栫粍瑁呰嚜 $.trash_reason
+鈥?applicant_type (STRING) - 鐢宠鏂圭被鍨嬨€傛爣璇嗙敱璋佸彂璧峰彇娑堬紝渚嬪鈥渃ustomer鈥濇垨鈥渟taff鈥濄€傛潵婧? 鏃犵洿鎺ュ瓧娈碉紝鍙兘渚濇嵁 $.trash_applicant_id 鏄惁涓洪【瀹D鎺ㄦ柇锛屽湪DWD澶勭悊銆?
+鈥?applicant_name (STRING) - 鍙栨秷鍙戣捣浜哄鍚嶃€傛潵婧? $.trash_applicant_name
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傚鐞嗗彇娑堢殑宸ヤ綔浜哄憳璐﹀彿銆傛潵婧? $.operator_id锛堝鏈夛級
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name锛堝鏈夛級
+(璇存槑: 鍔╂暀搴熼櫎璁板綍涓庡姪鏁欐湇鍔℃祦姘村瓨鍦ㄥ搴斿叧绯伙細褰撴煇鍔╂暀鏈嶅姟琚簾闄ゆ椂锛屽姪鏁欐祦姘存爣璁癷s_trash=1锛屽悓鏃朵骇鐢熶竴鏉″簾闄よ褰曡鏄庤鎯呫€傚湪ETL涓紝鍙埄鐢╫rder_trade_no鍜宻ite_assistant_id灏嗕袱鑰呭叧鑱旓紝纭繚涓嶄細閲嶅璁$畻璐圭敤锛堝簾闄ょ殑鏈嶅姟閫氬父涓嶈璐癸級銆傝琛ㄤ负涓氬姟鐩戞帶鏈嶅姟鍙栨秷鎯呭喌鎻愪緵鏁版嵁鏀寔銆?
+
+涓庡姪鏁欐祦姘寸殑鍏宠仈鍙婂簾闄ゅ彛寰勶紙鏂板锛?
+鍔╂暀搴熼櫎璁板綍琛ㄤ笌鍔╂暀娴佹按琛ㄤ箣闂寸殑鍏崇郴锛?
+鈥?涓€鏉″姪鏁欐湇鍔℃祦姘达紙鍔╂暀娴佹按琛ㄤ腑鐨勪竴鏉¤褰曪級锛屽湪琚簾闄ゆ椂锛屼細鍦ㄥ姪鏁欏簾闄よ〃涓骇鐢熶竴鏉″搴旇褰曘€?
+鈥?鍏宠仈閿€氬父鍖呮嫭锛?
+o order_trade_no锛堣鍗曚氦鏄撳彿锛夛紱
+o site_assistant_id锛堝姪鏁橧D锛夛紱
+o 蹇呰鏃惰繕鍙粨鍚堝彴妗孖D銆佹椂闂寸獥鍙h繘琛屽尮閰嶃€?
+搴熼櫎璁板綍涓昏鎵挎媴鍘熷洜璇存槑鍜岃矗浠诲綊灞炵殑浣滅敤锛屼緥濡傦細
+鈥?trash_reason / cancel_reason锛氬簾闄ゅ師鍥狅紝渚嬪鈥滈【瀹㈡洿鎹㈠姪鏁欌€濄€佲€滈【瀹复鏃剁鍦衡€濄€佲€滄湇鍔′笉婊℃剰鈥濈瓑銆?
+鈥?trash_applicant_id / trash_applicant_name锛氬彂璧峰簾闄ょ殑涓€鏂癸紙椤惧銆佸€肩彮缁忕悊绛夛級銆?
+鍦ㄨ璐瑰彛寰勪笂锛?
+鈥?鏄惁璁¤垂銆佽澶氬皯锛屼互鍔╂暀娴佹按涓殑 projected_income銆乮ncome_seconds銆乺eal_use_seconds 瀛楁涓哄噯銆?
+鈥?鍔╂暀搴熼櫎琛ㄦ湰韬笉鐩存帴瀛橀噾棰濓紝鍙槸琛ュ厖璇存槑鈥滀负浣曢儴鍒嗗師濮嬪簲鏀舵湭璁″叆钀ヤ笟鏀跺叆鈥濄€?
+鍚庣画鍦?DWD / DWS 灞傝繘琛屾敹鍏ュ垎鏋愭椂锛屽嚭鐜扳€滃師濮嬪簲鏀堕珮浜庡疄闄呭叆璐︹€濈殑宸紓锛屽彲閫氳繃鍏宠仈鍔╂暀搴熼櫎琛ㄦ煡鐪嬪師鍥犲垎甯冿紙渚嬪锛氶【瀹㈠師鍥?vs 鍔╂暀鍘熷洜锛夈€?
+
+group_buy_packages锛堝洟璐椁愬畾涔夎〃锛?
+鎻忚堪: 瀛樺偍闂ㄥ簵鍙敤鐨勫洟璐椁愬垪琛紝鍗充互鍥㈣喘褰㈠紡鍞崠鐨勪紭鎯犲椁愮殑閰嶇疆銆傛瘡鏉¤褰曞畾涔変竴绉嶅洟璐椁愮殑瑙勫垯锛屽寘鎷悕绉般€侀潰鍊笺€佹湁鏁堟湡銆侀€傜敤鏃舵銆侀檺瀹氬彴妗岀被鍨嬨€佷笂鏋剁姸鎬佺瓑銆?
+瀛楁瀹氫箟锛?
+鈥?package_id (BIGINT) - 鍥㈣喘濂楅ID锛屼富閿€傚敮涓€鏍囪瘑涓€绉嶅椁愩€傛潵婧怞SON璺緞: $.id
+鈥?tenant_id (BIGINT) - 绉熸埛ID銆傛潵婧? $.tenant_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?package_name (STRING) - 濂楅鍚嶇О銆備緥锛氣€滄棭鍦?灏忔椂鈥濃€滄柉璇哄厠涓ゅ皬鏃垛€濃€淜TV鍥涘皬鏃垛€濄€傛潵婧? $.name
+鈥?coupon_value (DECIMAL(10,2)) - 濂楅闈㈠€笺€傝濂楅鍙姷鎵g殑閲戦鎴栨湇鍔℃椂闀垮搴旂殑浠峰€硷紙閫氬父涓哄師浠凤級銆傛潵婧? $.coupon_money
+鈥?selling_price (DECIMAL(10,2)) - 閿€鍞环銆傛秷璐硅€呰喘涔版濂楅鎵€浠橀噾棰濓紙閫氬父浣庝簬闈㈠€硷級銆傛潵婧? $.sell_price锛堝鏈夛級
+鈥?valid_from (DATE) - 濂楅鏈夋晥鏈熻捣濮嬫棩鏈熴€傛潵婧? $.start_date
+鈥?valid_to (DATE) - 濂楅鏈夋晥鏈熺粨鏉熸棩鏈熴€傛潵婧? $.end_date
+鈥?valid_time_period (STRING) - 姣忔棩鍙敤鏃舵鎻忚堪銆傚鈥滄瘡鏃?9:00-18:00鍙敤鈥濄€傛潵婧? $.daily_time锛圝SON鍙兘鎻愪緵璧锋鏃堕棿瀛楁锛屾澶勫彲瀛樻枃鏈弿杩版垨鎷嗗垎瀛楁锛?
+鈥?limit_table_type (STRING) - 闄愬畾鍙版绫诲瀷銆傝鏄庢鍒稿彲鐢ㄧ殑鍙版鑼冨洿锛屼緥濡傗€滀粎闄愭柉璇哄厠鍖衡€濓紝鈥淜TV鍖呭帰閫傜敤鈥濄€傛潵婧? $.limit_table_type锛堝彲鑳介渶瑕佹牴鎹甁SON瀛楁缁勫悎锛屽闄愬畾鐨勫尯鍩?鍙扮被鍨嬶級
+鈥?limit_table_count (INT) - 姣忔鍙敤鍙版暟闄愬埗銆傚涓€涓鍗曚竴娆″彧鑳界敤涓€寮犲埜瀵瑰簲涓€寮犲彴銆傛潵婧? $.limit_table_count锛堝鏈夛級
+鈥?status (STRING) - 涓婃灦鐘舵€併€傜ず渚嬶細鈥渁ctive鈥濆湪鍞紝鈥渋nactive鈥濅笅鏋讹紝鈥渆xpired鈥濆凡杩囨湡銆傛潵婧? $.status锛堣嫢涓哄竷灏旀垨浠g爜锛孌WD灏嗙淮琛ㄦ槧灏勶級
+鈥?is_expired (TINYINT) - 鏄惁宸茶繃鏈熸爣蹇椼€?琛ㄧず濂楅宸茶繃鏈燂紙褰撳墠鏃ユ湡瓒呰繃valid_to锛夛紝0灏氬湪鏈夋晥鏈熴€傛潵婧? 渚濇嵁valid_to鐢盓TL鍒ゆ柇寰楀埌锛堟簮鏁版嵁濡傛湁鐩存帴瀛楁鍒欎娇鐢級
+鈥?platform (STRING) - 閿€鍞钩鍙般€傛寚璇ュ椁愬彂甯冪殑骞冲彴锛屽鈥滅編鍥⑩€濄€佲€滃ぇ浼楃偣璇勨€濓紝濡傛灉浠呴棬搴楄嚜鏈夊垯涓衡€淪ELF鈥濄€傛潵婧? 濡傛灉JSON鎻愪緵 platform 瀛楁鎴栭€氳繃dealId鍓嶇紑鎺ㄦ柇锛屽湪DWD澶勭悊銆?
+鈥?deal_id (STRING) - 澶栭儴骞冲彴Deal缂栧彿銆傚搴旂涓夋柟骞冲彴涓婄殑濂楅ID銆傛潵婧? $.dealId锛堝鏈夛級
+鈥?created_time (DATETIME) - 濂楅瀹氫箟鍒涘缓鏃堕棿銆傛潵婧? $.create_time
+鈥?updated_time (DATETIME) - 鏈€鍚庝慨鏀规椂闂淬€傛潵婧? $.update_time
+(璇存槑: 鍥㈣喘濂楅瀹氫箟鐢ㄤ簬鍒嗘瀽鍚勫椁愮殑浣跨敤鍜岄攢鍞儏鍐点€俵imit_table_type绛夊彲浠ュ湪DWD闃舵缁嗗寲涓哄叧鑱斿彴妗岀被鍨嬬淮搴︺€俻latform鑻ユ湁澶氫釜娓犻亾锛屽彲鍦ㄧ淮琛ㄤ腑鏋氫妇銆?
+group_buy_packages_LOG锛堝洟璐椁愪娇鐢ㄦ祦姘磋〃锛?
+鎻忚堪: 璁板綍鍥㈣喘濂楅鍒歌浣跨敤锛堟牳閿€锛夌殑娴佹按銆傛瘡鏉¤褰曡〃绀轰竴寮犲洟璐埜鍦ㄩ棬搴楃殑涓€娆′娇鐢紝閫氬父瀵瑰簲涓€涓鍗曠殑涓€閮ㄥ垎锛堜緥濡備娇鐢ㄥ埜鎶垫墸浜嗙壒瀹氬彴璐规椂闀匡級銆傚寘鍚鍗曚俊鎭€佹墍鐢ㄥ埜鐨処D/鍚嶇О銆佹姷鎵i噾棰濄€佷互鍙婃搷浣滃憳绛変俊鎭€?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鍥㈣喘鍒镐娇鐢ㄨ褰旾D锛屽敮涓€鏍囪瘑涓€娆″埜浣跨敤娴佹按銆傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€備娇鐢ㄨ鍒哥殑璁㈠崟缂栧彿銆傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傛潵婧? $.order_settle_id
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id
+鈥?site_table_id (BIGINT) - 鍙版ID銆傛湰鍒镐娇鐢ㄥ叧鑱旂殑鍙版锛堥€氬父鍒稿搴旀煇寮犲彴鐨勮垂鐢級銆傛潵婧? $.site_table_id
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傛潵婧? $.tableName
+鈥?package_id (BIGINT) - 鍥㈣喘濂楅ID銆傛爣璇嗘墍浣跨敤鍒稿睘浜庡摢绉嶅椁愬畾涔夛紝鍏宠仈group_buy_packages.package_id銆傛潵婧? $.deal_id 鎴?$.package_id锛堟牴鎹瓧娈靛惈涔夛紝鍙兘deal_id闇€鍖归厤濂楅瀹氫箟锛?
+鈥?package_name (STRING) - 濂楅鍚嶇О銆傚啑浣欒褰曞埜鍚嶇О锛屾潵婧? $.deal_name 鎴?$.package_name锛堝鏈夛級
+鈥?coupon_code (STRING) - 鍒哥爜銆傛秷璐硅€呰喘涔板悗鏀跺埌鐨勫埜缂栧彿銆傛潵婧? $.coupon_code锛堝鏈夛級
+鈥?deduct_amount (DECIMAL(10,2)) - 鍒告姷鎵i噾棰濄€備娇鐢ㄨ鍒告姷鎵g殑閲戦浠峰€笺€傛潵婧? $.deduct_money 鎴?$.coupon_deduct_money
+鈥?remaining_amount (DECIMAL(10,2)) - 鍒稿墿浣欓噾棰?浠峰€笺€傝嫢鍒稿彲閮ㄥ垎浣跨敤锛屽娆℃牳閿€鍒欒褰曞墿浣欏彲鐢ㄤ环鍊笺€傛潵婧? $.remain_money锛堝鏈夛級
+鈥?status (STRING) - 鍒镐娇鐢ㄧ姸鎬併€傚彲鑳界粺涓€涓衡€渦sed鈥濓紙宸叉牳閿€锛夛紝濡傛湁寮傚父鍒欐爣璁般€傚婧愭暟鎹彁渚涳紝鐢ㄤ簬纭鍒告垚鍔熶娇鐢ㄣ€傛潵婧? $.status锛堝鍏ㄩ儴宸茬敤鍙笉缁嗗垎锛?
+鈥?used_time (DATETIME) - 鍒镐娇鐢ㄦ椂闂淬€傛潵婧? $.create_time
+鈥?salesman_user_id (BIGINT) - 閿€鍞憳ID銆傚紩瀵煎敭鍒告垨鏍搁攢鐨勫憳宸ャ€傛潵婧? $.salesman_user_id
+鈥?salesman_name (STRING) - 閿€鍞憳濮撳悕銆傛潵婧? $.salesman_name
+鈥?operator_id (BIGINT) - 鏍搁攢鎿嶄綔鍛業D銆傚疄闄呭湪绯荤粺涓搷浣滈獙鍒哥殑鍛樺伐璐﹀彿銆傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鏍搁攢鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+(璇存槑: 鍥㈣喘濂楅浣跨敤璁板綍鍙互甯姪鍒嗘瀽鍥㈣喘鍒稿鏀跺叆鐨勮础鐚€俤educt_amount鍦ㄨ鍗曟眹鎬讳腑浼氫綋鐜颁负涓€绉嶆姌鎵?棰勪粯閮ㄥ垎銆俢oupon_code閫氬父瀵瑰簲绗笁鏂瑰钩鍙板彂鏀剧殑鍒哥爜锛屼絾鐢变簬杩樻湁骞冲彴楠屽埜璁板綍琛紝鍐呴儴璁板綍鍙兘鏈睍绀哄叿浣撳埜鐮併€俻ackage_id/鍚嶇О纭繚鍙叧鑱斿埌濂楅瀹氫箟缁村害銆?
+ODS_PLATFORM_COUPON_LOG锛堝钩鍙伴獙鍒歌褰曡〃锛?
+鎻忚堪: 璁板綍鏉ヨ嚜绗笁鏂瑰钩鍙扮殑鍥㈣喘鍒稿湪鏈棬搴楄鏍搁攢鐨勪簨浠躲€傛瘡鏉¤褰曞搴斾竴娆$涓夋柟鍒哥爜鐨勯獙璇佷娇鐢紝鎼哄甫骞冲彴鐩稿叧淇℃伅鍜岄棬搴楀唴閮ㄥ叧鑱斾俊鎭€傞€氬父涓庡洟璐椁愭祦姘村瓨鍦ㄤ竴涓€瀵瑰簲鍏崇郴銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 骞冲彴楠屽埜璁板綍ID锛屽敮涓€鏍囪瘑涓€娆$涓夋柟鍒告牳閿€浜嬩欢銆傛潵婧怞SON璺緞: $.id
+鈥?platform (STRING) - 鍒告潵婧愬钩鍙板悕绉般€傚鈥滅編鍥⑩€濄€佲€滃ぇ浼楃偣璇勨€濄€傛潵婧? 閫氳繃$.dealId鍓嶇紑鎴栭厤缃帹鏂钩鍙帮紝鍦―WD鏄犲皠鍒扮淮琛ㄣ€?
+鈥?deal_id (STRING) - 骞冲彴Deal ID銆傚搴旂涓夋柟骞冲彴鍥㈣喘椤圭洰鏍囪瘑銆傛潵婧? $.dealId
+鈥?certificate_id (STRING) - 鍒哥爜ID銆傜涓夋柟鍒哥殑鍞竴缂栫爜銆傛潵婧? $.certificateId
+鈥?order_id (BIGINT) - 闂ㄥ簵鍐呴儴璁㈠崟ID銆傛鍒稿叧鑱旂殑搴楀唴璁㈠崟ID锛堥潪浜ゆ槗鍙凤紝鍙兘瀵瑰簲siteOrderId锛夈€傛潵婧? $.orderId 鎴?$.order_id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛潵婧? 鑻SON鏈洿鎺ョ粰鍑猴紝鍙€氳繃鍐呴儴璁㈠崟ID鍦―WD闃舵鍏宠仈寰楀埌锛涘鏈夊瓧娈电洿鎺ユ彁渚涘垯濉叆銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.siteId
+鈥?site_table_id (BIGINT) - 鍙版ID銆傛鍒镐娇鐢ㄦ墍瀵瑰簲鐨勫彴妗屻€傛潵婧? $.site_table_id锛堝鏈夛級
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傛潵婧? $.tableName锛堝鏈夛級
+鈥?assistant_id (BIGINT) - 鍔╂暀ID銆傚鍒告秹鍙婂姪鏁欐湇鍔★紝鍙褰曠浉鍏冲姪鏁欒处鍙枫€傛潵婧? $.assistant_id锛堢寽娴嬪彲鑳芥病鏈夋瀛楁锛岃嫢鏈夊垯濉級
+鈥?used_time (DATETIME) - 鍒告牳閿€鏃堕棿銆傛潵婧? $.create_time
+鈥?operator_id (BIGINT) - 鏍搁攢鎿嶄綔鍛業D銆傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鏍搁攢鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+(璇存槑: 骞冲彴楠屽埜璁板綍閲嶇偣鍦ㄥ閮ㄥ埜淇℃伅锛坧latform, certificate_id绛夛級銆傚畠涓庡唴閮ㄥ洟璐椁愪娇鐢ㄨ褰曢€氳繃璁㈠崟鎴栧埜鐮佸叧鑱旓紝瀹為檯鍒嗘瀽鏃跺彲缁撳悎涓よ〃鏁版嵁銆傛ā鍨嬩腑淇濈暀璇ヨ〃浠ュ畬鏁磋褰曠涓夋柟骞冲彴鍒哥殑浣跨敤鏄庣粏銆俻latform瀛楁鍙兘涓嶇洿鎺ョ粰鍑猴紝鍦‥TL鏃跺彲渚濇嵁deal_id鎴朿ertificate_id缂栫爜瑙勫垯鍒ゆ柇锛屾垨閫氳繃閰嶇疆琛紙濡傚彧鏈夌編鍥竴绉嶅垯鍥哄畾涓虹編鍥級銆?
+payment_transactions锛堟敮浠樿褰曡〃锛?
+鎻忚堪: 瀛樺偍璁㈠崟鏀粯娴佹按锛屾瘡鏉¤褰曞搴旇鍗曠殑涓€绉嶄粯娆炬笭閬撶殑鏀舵鎯呭喌銆備竴绗旇鍗曞彲鑳芥媶鍒嗗绉嶆敮浠樻柟寮忥紙濡傞儴鍒嗙敤浼氬憳鍗′綑棰濓紝閮ㄥ垎寰俊锛夛紝鍒欎細鏈夊鏉℃敮浠樿褰曘€傝琛ㄥ弽鏄犳敹閾剁姣忕瑪瀹為檯鏀舵銆?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 鏀粯璁板綍ID锛屽敮涓€鏍囪瘑涓€鏉℃敮浠樻祦姘淬€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛鏀粯瀵瑰簲鐨勮鍗曠紪鍙枫€傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傛潵婧? $.order_settle_id
+鈥?pay_amount (DECIMAL(10,2)) - 鏀粯閲戦銆傛鏀粯娴佹按娑夊強鐨勯噾棰濄€傛鍊艰〃绀哄簵鍐呮敹娆撅紝璐熷€硷紙鍦ㄩ€€娆捐褰曚腑鍑虹幇锛夎〃绀哄簵鍐呮敮鍑恒€傛潵婧? $.pay_amount
+鈥?pay_method (INT) - 鏀粯鏂瑰紡浠g爜銆傝〃绀轰粯娆炬笭閬撶被鍨嬶紝渚嬪1=鐜伴噾銆?=寰俊銆?=鏀粯瀹濄€?=鍌ㄥ€煎崱绛夈€傘€愰渶閫氳繃缁磋〃鏄犲皠鍏蜂綋鍚嶇О銆戞潵婧? $.paymentMethod 鎴?$.pay_type
+鈥?pay_method_name (STRING) - 鏀粯鏂瑰紡鍚嶇О銆傚彲浠ュ湪ODS涓洿鎺ュ瓨鍌ㄦ枃瀛楋紝濡傗€滃井淇♀€濄€佲€滅幇閲戔€濓紙濡傛灉婧愮洿鎺ョ粰鍑轰簡锛夛紝鍚﹀垯鍦ㄧ淮搴﹁〃涓淮鎶ゆ槧灏勩€傛潵婧? $.payTypeName锛堝鏈夛級
+鈥?pay_status (INT) - 鏀粯鐘舵€佺爜銆?琛ㄧず瀹屾垚锛屽彲鑳?/1琛ㄧず澶勭悊涓?澶辫触绛夛紙鏈暟鎹泦涓潎涓?瀹屾垚锛夈€傛潵婧? $.pay_status
+鈥?transaction_id (STRING) - 澶栭儴鏀粯娴佹按鍙枫€傜涓夋柟鏀粯骞冲彴浜ゆ槗ID銆傛潵婧? $.transaction_id锛堝鏈夛級
+鈥?pay_time (DATETIME) - 鏀粯鏃堕棿銆傛潵婧? $.pay_time 鎴?$.create_time
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.siteProfile.id锛堟敮浠樿褰旿SON甯︽湁siteProfile蹇収锛?
+鈥?operator_id (BIGINT) - 鏀堕摱鎿嶄綔鍛業D銆傛潵婧? $.operator_id锛堝鏈夛級
+鈥?operator_name (STRING) - 鏀堕摱鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+(璇存槑: 鏀粯璁板綍琛ㄤ腑鐨勬瘡鏉¤褰曢€氬父搴斿搴斾簬璁㈠崟鐨勬煇涓敮浠樻柟寮忓疄闄呭埌璐﹂噾棰濄€傚璐﹀拰鍒嗘瀽鍚勬敮浠樻笭閬撴敹鍏ユ椂锛岀敤姝よ〃鐨勬暟鎹€傚浜庡偍鍊煎崱鏀粯锛宲ay_method鍙兘瀵瑰簲浼氬憳鍗℃墸娆撅紱鍏堕噾棰濆湪搴楀唴涓嶅舰鎴愭柊璧勯噾娴佸叆锛岃€屾槸鍐呴儴缁撹浆锛屼絾浠嶄綔涓烘敮浠樻柟寮忎箣涓€璁板綍銆俻ay_status鍩烘湰閮戒細鏄€滃畬鎴愨€濓紝棰濆鐘舵€佸彲蹇界暐鎴栫敤浜庡紓甯哥洃鎺с€?
+refund_transactions锛堥€€娆捐褰曡〃锛?
+鎻忚堪: 瀛樺偍鍙戠敓鐨勯€€娆炬祦姘达紝姣忔潯璁板綍浠h〃涓€绗旈€€娆炬搷浣滐紙灏嗛挶閫€杩樼粰椤惧鐨勪氦鏄擄級銆傞€氬父涓庢敮浠樿褰曞搴旓紝鐢ㄤ簬璐㈠姟鏍稿閫€娆炬敮鍑恒€?
+瀛楁瀹氫箟锛?
+鈥?id (BIGINT) - 閫€娆捐褰旾D锛屽敮涓€鏍囪瘑涓€娆¢€€娆句氦鏄撱€傛潵婧怞SON璺緞: $.id
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€傛閫€娆炬墍灞炵殑鍘熻鍗曠紪鍙枫€傛潵婧? $.order_trade_no
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆傛潵婧? $.order_settle_id
+鈥?refund_amount (DECIMAL(10,2)) - 閫€娆鹃噾棰濄€傝绗旈€€娆炬敮浠樼粰椤惧鐨勯噾棰濓紝閫氬父涓鸿礋鍊艰〃绀烘祦鍑恒€傛潵婧? $.pay_amount锛堟牱鏈腑鍧囦负璐熸暟锛?
+鈥?pay_method (INT) - 閫€娆炬笭閬撲唬鐮併€傚搴斿師鏀粯鐨勬笭閬撱€傛潵婧? $.paymentMethod 鎴?$.pay_type锛堝簲涓庢敮浠樿褰曠殑code涓€鑷达級
+鈥?pay_method_name (STRING) - 閫€娆炬笭閬撳悕绉般€傛潵婧? $.payTypeName锛堝鏈夛級
+鈥?pay_status (INT) - 閫€娆剧姸鎬佺爜銆傚€间负2琛ㄧず閫€娆惧畬鎴愶紙鏍锋湰鍏ㄤ负2锛夛紝0/1鍙兘琛ㄧず鏈鐞?澶勭悊涓€傛潵婧? $.pay_status
+鈥?original_pay_id (BIGINT) - 鍘熸敮浠樻祦姘碔D銆傛寚鏄庢湰娆¢€€娆惧搴斿摢绗旀敮浠樿褰曘€傛潵婧? $.relate_pay_id 鎴栫被浼煎瓧娈碉紙濡傛湁锛?
+鈥?refund_time (DATETIME) - 閫€娆炬椂闂淬€傛潵婧? $.create_time
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.site_id锛堥€氳繃siteProfile绛夛級
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傛墽琛岄€€娆剧殑鍛樺伐璐﹀彿銆傛潵婧? $.operator_id
+鈥?operator_name (STRING) - 鎿嶄綔鍛樺鍚嶃€傛潵婧? $.operator_name
+(璇存槑: 閫€娆捐褰曞彲鐢ㄤ簬涓庢敮浠樿褰曟牳瀵瑰簲鏀舵敮骞宠 銆傚湪璁㈠崟姹囨€诲垎鏋愭椂锛岄€€娆鹃€氬父涓嶈鍏ュ綋鏃ユ敹鍏ワ紝鑰屾槸鍐插噺鍘嗗彶璁㈠崟锛屽洜姝WS灞備細鏍规嵁闇€瑕佸鐞嗛€€娆惧奖鍝嶃€傛ā鍨嬩腑浠嶅皢閫€娆句簨瀹炶〃鐙珛瀛樺偍锛屾柟渚挎煡璇㈤€€娆炬€婚銆侀€€娆剧巼绛夋寚鏍囥€?
+ODS_ORDER_RECEIPT_DETAIL锛堢粨璐﹀皬绁ㄨ鎯呰〃锛?
+鎻忚堪: 瀛樺偍缁撶畻灏忕エ鐨勫畬鏁村揩鐓э紝姣忔潯璁板綍瀵瑰簲涓€寮犵粨璐﹀崟锛堜竴娆¤鍗曠粨绠楋級銆傚叾涓寘鍚棬搴椾俊鎭€佽鍗曟暣鍗曢噾棰濇眹鎬汇€佷細鍛樹娇鐢ㄦ儏鍐点€佷互鍙婅鍗曞唴鍚勫垎椤规槑缁嗭紙鍙拌垂銆佸晢鍝併€佸埜銆佹敮浠橈級绛夌粨鏋勫寲瀛愬璞°€傚彲瑙嗕负瀵圭粨璐﹁褰曠殑鎵╁睍璇︾粏鐗堛€?
+瀛楁瀹氫箟锛?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID锛屼富閿€傚敮涓€鏍囪瘑涓€寮犵粨绠楀崟銆傛潵婧怞SON璺緞: $.orderSettleId
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆傛潵婧? $.data.data.siteId锛堥€氳繃宓屽data鑾峰彇锛?
+鈥?tenant_id (BIGINT) - 绉熸埛ID銆傛潵婧? $.data.data.tenantId
+鈥?site_name (STRING) - 闂ㄥ簵鍚嶇О銆傛潵婧? $.data.data.shop_name
+鈥?site_address (STRING) - 闂ㄥ簵鍦板潃銆傛潵婧? $.data.data.full_address
+鈥?site_tel (STRING) - 闂ㄥ簵鐢佃瘽銆傛潵婧? $.data.data.business_tel
+鈥?cashier_name (STRING) - 鏀堕摱鍛樺鍚嶃€傚皬绁ㄤ笂鎵撳嵃鐨勬敹閾跺憳锛屽鈥滄敹閾跺憳:寮犱笁鈥濄€傛潵婧? $.data.data.cashierName
+鈥?member_name (STRING) - 浼氬憳濮撳悕蹇収銆傝嫢缁撹处鏃剁粦瀹氫簡浼氬憳锛屽垯璁板綍浼氬憳鍚嶇О锛屾湭缁戝畾鍒欏彲鑳芥樉绀衡€滃尶鍚嶇敤鎴封€濄€傛潵婧? $.data.data.memberName
+鈥?member_phone (STRING) - 浼氬憳鎵嬫満鍙峰揩鐓с€傛潵婧? $.data.data.memberPhone
+鈥?member_point (DECIMAL(10,2)) - 浼氬憳绉垎蹇収銆傜粨璐︽椂浼氬憳绉垎浣欓銆傛潵婧? $.data.data.memberPoint
+鈥?total_amount (DECIMAL(10,2)) - 璁㈠崟鎬婚噾棰濓紙鍘熶环鎬昏锛夈€傚嵆鎵€鏈夋秷璐归」鏈姌鎵e墠鍚堣閲戦銆傛潵婧? $.data.data.orderItem[*].price绛夋眹鎬伙紙濡傛棤鐩存帴瀛楁鍒橢TL璁$畻锛?
+鈥?total_discount (DECIMAL(10,2)) - 鏁村崟鎶樻墸鎬婚銆傚寘鍚細鍛樻姌鎵e拰浜哄伐浼樻儬鐨勬€诲拰銆傛潵婧? 鍚勬槑缁嗘姌鎵d箣鍜岋紙濡傛棤鐩存帴瀛楁锛孍TL姹囨€昏绠楋級
+鈥?coupon_deduct_total (DECIMAL(10,2)) - 鍒告姷鎵f€婚銆備娇鐢ㄥ洟璐埜绛夋姷鎵g殑鎬婚噾棰濄€傛潵婧? $.data.data.couponItem[*].couponMoney绛夋眹鎬?
+鈥?prepaid_deduct (DECIMAL(10,2)) - 浼氬憳鍗″偍鍊兼姷鎵i噾棰濄€傛湰鍗曚娇鐢ㄤ細鍛樺偍鍊煎崱鏀粯鐨勯噾棰濄€傛潵婧? $.data.data.memberDeductAmount
+鈥?amount_receivable (DECIMAL(10,2)) - 搴旀敹閲戦銆傚嵆鎵i櫎鎵€鏈夋姌鎵e埜鍚庨【瀹㈤渶鏀粯鐨勯噾棰濄€傛潵婧? 璁$畻寰楀埌锛坱otal_amount - total_discount - coupon_deduct_total锛夋垨 $.data.data.ledgerAmount
+鈥?amount_paid (DECIMAL(10,2)) - 瀹炴敹閲戦銆傞【瀹㈠疄闄呮敮浠樼殑閲戦鎬昏锛堝寘鎷偍鍊煎崱鏀粯鍜屽叾浠栨敮浠橈級銆傛潵婧? $.data.data.actualPayment
+鈥?pay_method_count (INT) - 鏀粯鏂瑰紡绉嶇被鏁般€傝璁㈠崟浣跨敤鐨勬敮浠樻笭閬撴暟閲忥紙濡傜敤涓ょ鏂瑰紡鏀粯鍒欎负2锛夈€傛潵婧? 鏀粯鏄庣粏count
+鈥?pay_details (STRING) - 鏀粯璇︽儏鎽樿銆傚皢鍚勬敮浠樻柟寮忓強閲戦鎷兼帴鎻忚堪锛屽鈥滃井淇?0鍏?浼氬憳鍗?0鍏冣€濄€傛潵婧? 鏉ヨ嚜鏀粯鏄庣粏鍒楄〃鎷兼帴锛圗TL缁勮锛?
+鈥?refund_amount (DECIMAL(10,2)) - 閫€娆鹃噾棰濄€傝嫢璇ヨ鍗曞彂鐢熼€€娆撅紝鍒欒褰曢€€娆炬€婚锛堜竴鑸礋鍊硷級銆傛潵婧? 鍏宠仈閫€娆捐褰曡绠?
+鈥?settle_time (DATETIME) - 缁撹处鏃堕棿銆傝鍗曞畬鎴愮粨绠楃殑鏃堕棿銆傛潵婧? $.data.data.createTime 鎴?$.data.data.payTime锛堥渶纭JSON瀛楁锛?
+鈥?order_items_json (JSON) - 璁㈠崟鍟嗗搧鏄庣粏JSON銆傚祵鍏ュ師濮嬪晢鍝佸垪琛ㄧ粨鏋勶紝浠SON淇濆瓨锛堝寘鍚瘡涓晢鍝佸悕绉般€佹暟閲忋€佷环鏍肩瓑锛夈€傛潵婧? $.data.data.orderItem 瀵硅薄
+鈥?table_fee_json (JSON) - 鍙拌垂鏄庣粏JSON銆傚祵鍏ュ師濮嬪彴璐逛娇鐢ㄦ槑缁嗐€傛潵婧? $.data.data.taiFeeItem
+鈥?coupon_json (JSON) - 鍒镐娇鐢ㄦ槑缁咼SON銆傚祵鍏ュ師濮嬪埜椤瑰垪琛ㄣ€傛潵婧? $.data.data.couponItem
+鈥?payment_json (JSON) - 鏀粯鏄庣粏JSON銆傚祵鍏ュ師濮嬫敮浠樺垪琛ㄣ€傛潵婧? $.data.data.paymentItem 鎴?$.data.data.payList
+(璇存槑: 缁撹处灏忕エ璇︽儏ODS琛ㄧ敱浜庣粨鏋勫鏉傦紝閮ㄥ垎瀛楁浠ュ祵鍏SON褰㈠紡淇濆瓨浠ラ槻淇℃伅涓㈠け锛屼絾鍦―WD灞備細鎷嗚В鏁村悎鍚屾鍒扮浉搴斾簨瀹炶〃銆傝琛ㄤ富瑕佺敤浜庢牳瀵瑰拰琛ュ厖璁㈠崟姹囨€讳俊鎭€備緥濡傛敮浠樿鎯呭彲浠ヨВ鏋愪絾姝ゅ涔熶繚鐣欐枃鏈柟渚挎煡璇€倀otal_amount銆乼otal_discount绛夊彲浠TL闃舵浠庡悇瀛愰」姹囨€诲緱鍒帮紝浠ョ‘淇濆噯纭€俽efund_amount闇€缁撳悎閫€娆捐〃璁$畻锛屽洜涓哄皬绁ㄨ鎯呭彲鑳戒笉鐩存帴浣撶幇閫€娆俱€傛ODS琛ㄥ湪ETL涓篃鐢ㄤ簬鐢熸垚DWS璁㈠崟姹囨€诲琛ㄣ€?
+________________________________________
+浠ヤ笂鍒楀嚭浜嗕富瑕丱DS灞傝〃鍙婂瓧娈点€傚鏈夋簮鏁版嵁鏂板妯″潡锛孫DS灞傚彲鎸夌被浼兼柟寮忔墿灞曘€?
+3. DWD灞傝〃瀹氫箟锛堟槑缁嗗眰锛岀淮搴﹁〃涓庝簨瀹炶〃锛?
+DWD灞傚湪ODS鐨勫熀纭€涓婅繘琛屾竻娲楀姞宸ワ紝寰楀埌浼佷笟涓氬姟鍒嗘瀽鐨勭淮搴﹁〃鍜屼簨瀹炶〃銆傜淮搴﹁〃锛圖IM锛夋暣鐞嗕富鏁版嵁锛屽闂ㄥ簵銆佷細鍛樸€佸晢鍝併€佸姪鏁欑瓑锛屼簨瀹炶〃锛團ACT锛変繚瀛樹笟鍔′簨鍔℃槑缁嗭紝濡傞攢鍞€佸彴璐广€佸姪鏁欐湇鍔°€佹敹娆剧瓑銆侱WD灞傚瓧娈靛懡鍚嶈鑼冪粺涓€銆佸惈涔夋竻鏅帮紝骞跺凡鍓旈櫎鏃犳晥鏁版嵁銆佸叧鑱斿埌鐩稿簲缁村害ID銆傛墍鏈夋灇涓剧被瀛楁鍦ㄦ灞傞€氳繃缁磋〃缈昏瘧鎴栦互缁磋〃ID鏇夸唬锛岄伩鍏嶇洿鎺ュ瓨鍌ㄤ唬鐮併€備互涓嬪垎鍒垪鍑虹淮搴﹁〃鍜屾槑缁嗕簨瀹炶〃璁捐锛?
+缁村害琛ㄥ瓧娈垫潵婧愭€讳綋閬靛惊锛?
+鈥?鑻ョ淮琛ㄦ槸 ODS 鍚屾鐨勨€滀富鏁版嵁鈥濓紙濡?dim_member, dim_product, dim_table, dim_assistant锛夛紝鍒?DWD 瀛楁涓?ODS 瀛楁鍩烘湰鍚屽悕涓€涓€瀵瑰簲锛屽瓧娈电骇 JSON 璺緞浠?ODS 绔犺妭涓哄噯锛?
+鈥?DWD 鍙湪浠ヤ笅鎯呭喌澧炲姞/閲嶅懡鍚嶅瓧娈碉細缁熶竴闂ㄥ簵/绉熸埛涓婚敭锛坱enant_id, site_id锛夈€佹娊鍙栧垎绫?鍥㈤槦绛夋灇涓惧埌涓撻棬缁磋〃銆佸鍔犵姸鎬佹弿杩板瓧娈电瓑銆?
+鍙互鍦?PRD 涓粺涓€鍔犱竴鍙ョ害瀹氾紝渚嬪锛?
+闄ゆ湰绔犺妭鐗瑰埆娉ㄦ槑鐨勨€滆鐢?閲嶅懡鍚嶅瓧娈碘€濆锛屾墍鏈?DWD 缁村害琛ㄥ瓧娈靛潎涓庡搴?ODS 琛ㄥ瓧娈靛悓鍚嶄竴涓€鏄犲皠锛涘瓧娈电殑 JSON 鏉ユ簮璺緞浠?ODS 琛ㄧ珷鑺傚畾涔変负鍑嗭紝涓嶅湪 DWD 閲嶅銆?
+
+3.1 缁村害琛ㄥ畾涔?
+DIM_SITE锛堥棬搴楃淮搴﹁〃锛?
+ 涓氬姟瀹氫箟
+
+`dim_site` 缁熶竴鎵胯浇闂ㄥ簵涓绘暟鎹紝鏄墍鏈変簨瀹炶〃鍜?DWS 瀹借〃鐨勯棬搴楀綊灞炵淮搴︺€?
+
+- 涓氬姟灞傞潰鐨?*鏍稿績瀹炰綋鏄棬搴楋紙site锛?*锛?
+- **鎵€鏈変簨瀹炶〃銆佹眹鎬昏〃鍧囬€氳繃 `site_id` 鍏宠仈鍒?dim_site**锛?
+- 绉熸埛/鍝佺墝锛坱enant锛変俊鎭?*涓嶅啀鍗曠嫭寤虹淮琛?*锛屼粎浣滀负 `dim_site` 鐨勫睘鎬у瓨鍦紙濡?`tenant_name`锛夈€?
+
+涓婃父鍚勭被 JSON 涓嚭鐜扮殑 `site_id`銆乣siteProfile` 绛夐棬搴椾俊鎭紝鍦?ODS 灞備互鍘熷蹇収淇濈暀锛屽湪 DWD 灞傜粺涓€鎶藉彇鍒?`dim_site`锛岄伩鍏嶅湪浜嬪疄灞傞噸澶嶅祵鍏?`siteProfile` 缁撴瀯銆?
+
+瀛楁璁捐涓?JSON 鏄犲皠
+
+| 瀛楁鍚? | 绫诲瀷 | 璇存槑 | 鍏稿瀷 JSON 鏉ユ簮绀轰緥 |
+|----------------|--------------------|------------------------------------------------------------|---------------------------------------------------------|
+| `site_id` | BIGINT | 闂ㄥ簵 ID锛屼富閿? | 灏忕エ璇︽儏锛歚$.data.data.siteId`锛?br>鍏跺畠鍚?siteProfile 鐨?JSON 涓殑 `siteProfile.id` |
+| `tenant_name` | VARCHAR(200) | 鍝佺墝/绉熸埛鍚嶇О锛屼粎浣滀负鎻忚堪灞炴€э紝涓嶄綔涓轰簨瀹炲眰鍏宠仈閿? | 鍙敱閰嶇疆鎴栭涓棬搴楀揩鐓т汉宸ユ寚瀹氾紝濡傗€滄湕鏈楁鐞冣€濈瓑 |
+| `site_code` | VARCHAR(50) | 闂ㄥ簵缂栫爜锛堝涓婃父鏈夊崟鐙紪鐮侊紝鍙负绌猴級 | 灏忕エ璇︽儏锛歚$.data.data.shop_code` 鎴?siteProfile 涓悓涔夊瓧娈?|
+| `site_name` | VARCHAR(200) | 闂ㄥ簵鍚嶇О | 灏忕エ璇︽儏锛歚$.data.data.shop_name`锛泂iteProfile.name |
+| `full_address` | VARCHAR(500) | 闂ㄥ簵瀹屾暣鍦板潃 | 灏忕エ璇︽儏锛歚$.data.data.full_address` |
+| `city_name` | VARCHAR(100) | 鍩庡競鍚嶇О锛堝彲鐢卞湴鍧€鎴栧尯鍩?ID 瑙f瀽锛岃В鏋愪笉鍒板垯涓虹┖锛? | 鐢?`full_address` 鎴?`tenant_site_region_id` 瑙f瀽 |
+| `district_name`| VARCHAR(100) | 鍖?鍘垮悕绉帮紙鍙€夛級 | 鍚屼笂 |
+| `longitude` | DECIMAL(10,6) | 缁忓害 | siteProfile锛歚$.longitude`锛堝鏈夛級 |
+| `latitude` | DECIMAL(10,6) | 绾害 | siteProfile锛歚$.latitude`锛堝鏈夛級 |
+| `business_tel` | VARCHAR(50) | 闂ㄥ簵鐢佃瘽 | 灏忕エ璇︽儏锛歚$.data.data.business_tel` |
+| `open_date` | DATE | 寮€搴楁棩鏈燂紙濡傛棤鍒欎负绌猴紝鍚庣画鍙汉宸ョ淮鎶わ級 | 鏃犵洿鎺ュ瓧娈垫椂鐢变笟鍔′晶琛ュ綍 |
+| `status` | VARCHAR(50) | 闂ㄥ簵鐘舵€侊細钀ヤ笟涓?/ 鍋滀笟 / 绛瑰绛? | 濡備笂娓告湁闂ㄥ簵鐘舵€侀厤缃垯鏄犲皠锛涘綋鍓嶅彲榛樿鈥滆惀涓氫腑鈥? |
+| `org_id` | BIGINT | 缁勭粐/鍖哄煙 ID锛堝鏈夛紝濡傜鎴蜂晶鐨勫尯鍩熸爲锛? | siteProfile锛歚$.tenant_site_region_id` 鎴?`$.org_id` |
+| `remark` | VARCHAR(500) | 澶囨敞 | 鏁颁粨渚х淮鎶? |
+| `created_at` | TIMESTAMP | 璁板綍鍒涘缓鏃堕棿锛堟暟浠擄級 | 鏁颁粨 ETL 鐢熸垚 |
+| `updated_at` | TIMESTAMP | 璁板綍鏈€鍚庢洿鏂版椂闂达紙鏁颁粨锛? | 鏁颁粨 ETL 鐢熸垚 |
+
+> 璇存槑锛?
+> - 涓婃父 JSON 涓殑 `tenant_id` 鍦?DWD 灞?*涓嶅啀鐢ㄤ簬寤烘ā鍏宠仈**锛屽鏈夐渶瑕佸彲鍦?DIM_SITE 澧炲姞涓€涓?`tenant_code` 瀛楁浣滀负绾弿杩?瀵圭収鐢紱
+> - 浠讳綍鍝佺墝/绉熸埛缁村害鍒嗘瀽锛岀粺涓€閫氳繃锛歚site_id -> dim_site.tenant_name` 瀹炵幇銆?
+
+#### 寤鸿〃 SQL 鑽夋锛圥ostgreSQL锛?
+
+```sql
+CREATE TABLE dim_site (
+ site_id BIGINT PRIMARY KEY, -- 闂ㄥ簵ID锛屽搴斿悇涓氬姟琛ㄤ腑鐨?site_id
+ tenant_name VARCHAR(200) NOT NULL, -- 鍝佺墝/绉熸埛鍚嶇О锛屼粎浣滀负灞炴€?
+ site_code VARCHAR(50), -- 闂ㄥ簵缂栫爜锛堥€夊~锛?
+ site_name VARCHAR(200) NOT NULL, -- 闂ㄥ簵鍚嶇О
+ full_address VARCHAR(500), -- 瀹屾暣鍦板潃
+ city_name VARCHAR(100), -- 鍩庡競
+ district_name VARCHAR(100), -- 鍖?鍘?
+ longitude DECIMAL(10,6), -- 缁忓害
+ latitude DECIMAL(10,6), -- 绾害
+ business_tel VARCHAR(50), -- 闂ㄥ簵鐢佃瘽
+ open_date DATE, -- 寮€搴楁棩鏈燂紙鍙负绌猴級
+ status VARCHAR(50) DEFAULT '钀ヤ笟涓?, -- 闂ㄥ簵鐘舵€侊紙榛樿钀ヤ笟涓級
+ org_id BIGINT, -- 缁勭粐/鍖哄煙ID锛堝鏈夛級
+ remark VARCHAR(500), -- 澶囨敞
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, -- 璁板綍鍒涘缓鏃堕棿锛堟暟浠擄級
+ updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 璁板綍鏇存柊鏃堕棿锛堟暟浠擄級
+);
+
+COMMENT ON TABLE dim_site IS '闂ㄥ簵缁村害琛紝缁熶竴瀛樻斁闂ㄥ簵涓绘暟鎹紝鏀寔澶氶棬搴楁墿灞曪紱绉熸埛/鍝佺墝淇℃伅浠呬綔涓哄睘鎬у瓨鍦?;
+
+COMMENT ON COLUMN dim_site.site_id IS '闂ㄥ簵ID锛屼笂娓稿悇JSON涓殑site_id缁熶竴鏄犲皠鍒版';
+COMMENT ON COLUMN dim_site.tenant_name IS '鍝佺墝/绉熸埛鍚嶇О锛屼粎浣滀负鎻忚堪灞炴€э紝浜嬪疄琛ㄤ笉鐩存帴鍏宠仈绉熸埛缁?;
+COMMENT ON COLUMN dim_site.site_code IS '闂ㄥ簵缂栫爜锛堝涓婃父鏈夊崟鐙紪鐮侊紝鍙负绌猴級';
+COMMENT ON COLUMN dim_site.site_name IS '闂ㄥ簵鍚嶇О';
+COMMENT ON COLUMN dim_site.full_address IS '闂ㄥ簵瀹屾暣鍦板潃';
+COMMENT ON COLUMN dim_site.city_name IS '鍩庡競鍚嶇О';
+COMMENT ON COLUMN dim_site.district_name IS '鍖?鍘垮悕绉?;
+COMMENT ON COLUMN dim_site.longitude IS '缁忓害';
+COMMENT ON COLUMN dim_site.latitude IS '绾害';
+COMMENT ON COLUMN dim_site.business_tel IS '闂ㄥ簵鐢佃瘽';
+COMMENT ON COLUMN dim_site.open_date IS '寮€搴楁棩鏈?;
+COMMENT ON COLUMN dim_site.status IS '闂ㄥ簵鐘舵€侊細钀ヤ笟涓?鍋滀笟/绛瑰绛?;
+COMMENT ON COLUMN dim_site.org_id IS '闂ㄥ簵鎵€灞炵粍缁?鍖哄煙ID锛堝涓婃父鏈塼enant_site_region_id锛?;
+COMMENT ON COLUMN dim_site.remark IS '澶囨敞';
+COMMENT ON COLUMN dim_site.created_at IS '璁板綍鍒涘缓鏃堕棿锛堟暟浠撲晶锛?;
+COMMENT ON COLUMN dim_site.updated_at IS '璁板綍鏈€鍚庢洿鏂版椂闂达紙鏁颁粨渚э級';
+DIM_MEMBER锛堜細鍛樼淮搴﹁〃锛?
+鎻忚堪锛?浼氬憳缁村害锛岃褰曚細鍛樹釜浜哄強璐︽埛灞炴€с€傚皢ODS浼氬憳妗f鍜屼細鍛樺崱淇℃伅鍚堝苟锛屾彁渚涘畬鏁翠細鍛樼敾鍍忋€?
+涓婚敭: member_id锛堜細鍛樿处鎴稩D锛?
+瀛楁:
+鈥?member_id (BIGINT) - 浼氬憳ID锛屼富閿€傚搴擮DS_MEMBER_PROFILE.id銆?
+鈥?member_name (STRING) - 浼氬憳濮撳悕銆傛潵鑷狾DS_MEMBER_PROFILE.real_name锛屽涓虹┖鍒欑敤鏄电О浠f浛銆?
+鈥?nickname (STRING) - 浼氬憳鏄电О銆?
+鈥?gender (STRING) - 鎬у埆锛堚€滅敺鈥?鈥滃コ鈥濓級銆傜敱member_profiles.gender浠g爜缈昏瘧寰楀埌銆?
+鈥?birthday (DATE) - 鍑虹敓鏃ユ湡銆?
+鈥?mobile (STRING) - 鎵嬫満鍙风爜銆?
+鈥?member_type_id (BIGINT) - 浼氬憳鍗$被鍨婭D锛屽閿弬鐓IM_MEMBER_CARD_TYPE.card_type_id銆?
+鈥?member_type_name (STRING) - 浼氬憳鍗$被鍨嬪悕绉般€傚鈥滃偍鍊煎崱鈥濄€佲€滈摱鍗♀€濄€佲€滈噾鍗♀€濈瓑銆?
+鈥?status (STRING) - 浼氬憳鐘舵€併€傜炕璇慜DS_MEMBER_PROFILE.status鏋氫妇锛屽鈥滄甯糕€濄€佲€滃仠鐢ㄢ€濄€?
+鈥?register_time (DATETIME) - 娉ㄥ唽鏃堕棿/寮€鍗℃椂闂淬€?
+鈥?valid_from (DATE) - 浼氬憳鍗℃湁鏁堟湡寮€濮嬨€?
+鈥?valid_to (DATE) - 浼氬憳鍗℃湁鏁堟湡鎴銆?
+鈥?last_visit_time (DATETIME) - 鏈€杩戞秷璐规椂闂淬€?
+鈥?balance (DECIMAL(10,2)) - 褰撳墠鍌ㄥ€间綑棰濓紙鍏冿級銆?
+鈥?total_recharge_amount (DECIMAL(10,2)) - 鍘嗗彶鍏呭€兼€婚锛堝厓锛夈€?鍙互鍦‥TL鍒濆鍖栨椂璁$畻鎴栧悗缁疮璁?
+鈥?total_consumed_amount (DECIMAL(10,2)) - 鍘嗗彶娑堣垂鎬婚锛堝偍鍊奸儴鍒嗭紝鍏冿級銆?
+鈥?wechat_id (STRING) - 缁戝畾寰俊鍙稩D銆?
+鈥?alipay_id (STRING) - 缁戝畾鏀粯瀹濆彿ID銆?
+鈥?remark (STRING) - 澶囨敞銆?
+(鏉ユ簮: 涓昏鏉ヨ嚜member_profiles瀛楁锛宮ember_type鐩稿叧鍒欑粨鍚圤DS_MEMBER_CARD鎴栭厤缃〃纭畾銆傚鍗$被鍨嬪拰鏈夋晥鏈熶粠member_stored_value_cards鎻愬彇銆備綑棰濆彇member_profiles.balance锛屼絾鍦ㄥ垎鏋愪腑鏇村彲闈犵殑鏄€氳繃浣欓鍙樻洿娴佹按璁$畻锛岃繖閲屼繚鐣欎竴涓揩鐓у€笺€傚厖鍊?娑堣垂鎬婚鍙湪ETL鎴朆I灞傞€氳繃浜嬪疄琛ㄦ眹鎬诲緱鍒帮紝涓嶄竴瀹氬湪缁磋〃瀛樺偍銆傚垵濮嬪彲涓嶅~鎴栭€氳繃鍘嗗彶璁$畻鏇存柊銆侱IM_MEMBER涓庝簨瀹炶〃鍏宠仈鏃讹紝閫氳繃member_id杩炴帴銆?
+DIM_MEMBER_CARD_TYPE锛堜細鍛樺崱绫诲瀷缁村害琛級
+鎻忚堪锛?浼氬憳鍗$绫荤淮搴︺€傛弿杩板悇绉嶄細鍛樺崱绾у埆鎴栫被鍨嬬殑瀹氫箟灞炴€э紝渚嬪鍚嶇О銆佹姌鎵c€佹潈鐩娿€傞伩鍏嶅湪妯″瀷涓‖缂栫爜浼氬憳鍗℃灇涓俱€?
+涓婚敭: card_type_id
+瀛楁:
+鈥?card_type_id (BIGINT) - 鍗$ID锛屼富閿€?
+鈥?card_type_name (STRING) - 鍗$鍚嶇О銆?
+鈥?discount_rate (DECIMAL(5,2)) - 榛樿鎶樻墸鐜囥€傚0.90琛ㄧず鎵撲節鎶樸€?
+鈥?description (STRING) - 鍗$鎻忚堪/鏉冪泭璇存槑銆?
+鈥?remark (STRING) - 澶囨敞銆?
+(鏉ユ簮: 缁撳悎涓氬姟閰嶇疆銆傚綋鍓嶅彲浠嶰DS_MEMBER_CARD涓眹鎬讳笉鍚宑ard_type_id鍙婂悕绉帮紝濉厖杩涙缁磋〃锛屼緥濡傚偍鍊煎崱涓€绫伙紝娆″崱鍙︿竴绫荤瓑锛屽苟璁板綍鍏舵姌鎵h鍒欍€傚鏃犳洿澶氫俊鎭彲鏆傚瓨绌烘弿杩帮紝鐢变笟鍔¤ˉ鍏呫€?
+DIM_PRODUCT锛堝晢鍝佺淮搴﹁〃锛?
+鎻忚堪锛?鍟嗗搧缁村害锛屾弿杩板搧鐗屽晢鍝佺殑灞炴€с€傜敱ODS_PRODUCT娓呮礂鑰屾潵锛屽苟鍏宠仈鍟嗗搧绫诲埆绛変俊鎭€?
+涓婚敭: goods_id
+瀛楁:
+鈥?goods_id (BIGINT) - 鍟嗗搧ID锛屼富閿€?
+鈥?goods_name (STRING) - 鍟嗗搧鍚嶇О銆?
+鈥?goods_code (STRING) - 鍟嗗搧缂栫爜銆?
+鈥?category_id (BIGINT) - 鍟嗗搧绫诲埆ID锛屽閿弬鐓IM_PRODUCT_CATEGORY.category_id銆?
+鈥?category_name (STRING) - 鍟嗗搧绫诲埆鍚嶇О銆?
+鈥?unit (STRING) - 璁¢噺鍗曚綅銆?
+鈥?is_service (TINYINT) - 鏄惁鏈嶅姟绫诲晢鍝侊紙1鏈嶅姟/0鍟嗗搧锛夈€?
+鈥?status (STRING) - 鍟嗗搧鐘舵€侊紙鈥滀笂鏋垛€?鈥滀笅鏋垛€濓級銆?
+鈥?site_id (BIGINT) 鈥?闂ㄥ簵ID銆?
+(鏉ユ簮: ODS_PRODUCT锛屽幓闄や笉闇€瑕佸垎鏋愮殑瀛楁锛屼粎淇濈暀鏍稿績灞炴€с€俢ategory_id瀵瑰簲DIM_PRODUCT_CATEGORY浠ヨ幏寰楃被鍒悕绉般€俿tatus鐢变唬鐮佽浆鎴愭枃鏈€俿ite_id涓轰簡閾捐矾瀹屾暣涔熷瓨鍌ㄣ€?
+DIM_PRODUCT_CATEGORY锛堝晢鍝佺被鍒淮搴﹁〃锛?
+鎻忚堪锛?鍟嗗搧鍒嗙被缁村害銆傚瓨鍌ㄥ晢鍝佺殑绫诲埆灞傛淇℃伅锛屽澶х被銆佸瓙绫诲悕绉帮紝鐢ㄤ簬鎸夊搧绫诲垎鏋愰攢鍞€?
+涓婚敭: category_id
+瀛楁:
+鈥?category_id (BIGINT) - 鍒嗙被ID锛屼富閿€?
+鈥?category_name (STRING) - 鍒嗙被鍚嶇О銆?
+鈥?parent_category_id (BIGINT) - 鐖剁被鍒獻D锛堝鏈変笂涓嬬骇锛夈€?
+鈥?parent_category_name (STRING) - 鐖剁被鍒悕绉般€?
+鈥?is_active (TINYINT) - 鏄惁鍦ㄧ敤锛?鏄?0鍚︼級銆?
+(鏉ユ簮: 搴撳瓨鍙樺寲璁板綍2.json 涓В鏋?goodsCategoryList 鑾峰彇銆傜敱浜庡簱瀛樺彉鍖栬褰?瀹為檯鏄竴浠藉晢鍝佸垎绫婚厤缃爲锛屽叾姣忔潯璁板綍涓轰竴涓垎绫昏妭鐐广€侲TL闇€閬嶅巻鎻愬彇category_id銆乶ame鍜宲arent_id鏋勫缓缁磋〃銆傚垎绫诲眰绾у叧绯诲彲鐢ㄤ簬鎸夊ぇ绫?灏忕被姹囨€婚攢鍞€傚綋鍓嶆暟鎹墍鏈夊垎绫?is_warehousing=1 琛ㄧず鍙備笌搴撳瓨绠$悊锛屽潎鍙涓烘湁鏁堝垎绫汇€?
+DIM_TABLE锛堝彴妗岀淮搴﹁〃锛?
+鎻忚堪锛?鍙版缁村害锛屾弿杩伴棬搴楀唴鍚勫彴妗?鍖呭帰鐨勫睘鎬э紝濡傜紪鍙枫€佸尯鍩熴€佺被鍨嬬瓑銆傜敱ODS_TABLE_INFO鍔犲伐寰楀埌銆?
+涓婚敭: site_table_id
+瀛楁:
+鈥?site_table_id (BIGINT) - 鍙版ID锛屼富閿€?
+鈥?table_name (STRING) - 鍙版鍚嶇О銆?
+鈥?table_no (STRING) - 鍙版缂栧彿锛堢函鏁板瓧搴忓彿锛屽鏈夌殑璇濓級銆?
+鈥?area_name (STRING) - 鍖哄煙鍚嶇О銆?
+鈥?table_type (STRING) - 鍙版绫诲瀷锛堜緥濡傗€滅編寮忔鈥濄€佲€滄柉璇哄厠妗屸€濄€佲€淜TV鍖呴棿鈥濄€佲€滈夯灏嗘埧鈥濓級銆?
+鈥?is_vip (TINYINT) - 鏄惁VIP涓撳睘鍙般€?
+鈥?status (STRING) - 鍙版鐘舵€侊紙鈥滃惎鐢ㄢ€?鈥滃仠鐢ㄢ€濓級銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+(鏉ユ簮: 涓昏瀛楁鏉ヨ嚜ODS_TABLE_INFO锛宎rea_name鍜宼able_type鍙兘闇€瑕佺粨鍚堥厤缃垨鍚嶇О瑙勫垯濉厖銆備緥濡?area_name 閫氳繃ODS_TABLE_INFO.area_id鍏宠仈闂ㄥ簵鍖哄煙閰嶇疆琛?濡傛灉鏈?鑾峰彇鍚嶇О锛屾病鏈夊垯浠巘able_name瑙f瀽銆倀able_type鍙熀浜巘able_name涓叧閿瓧鏄犲皠锛屽鍚€滄柉鈥濆瓧鐨勪负鏂鍏嬫锛屽湪缁磋〃涓粺涓€绠$悊鏄犲皠鍏崇郴閬垮厤纭紪鐮併€?
+DIM_ASSISTANT锛堝姪鏁欑淮搴﹁〃锛?
+鎻忚堪锛?鍔╂暀锛堟湇鍔′汉鍛橈級缁村害锛岃褰曞憳宸?鍔╂暀鐨勫睘鎬с€傜敱assistant_accounts_master娓呮礂寰楀埌锛屽寘鎷叾涓汉淇℃伅鍜岀姸鎬佺瓑銆?
+涓婚敭: assistant_id
+瀛楁:
+鈥?assistant_id (BIGINT) - 鍔╂暀ID锛堣处鍙稩D锛夛紝涓婚敭銆?
+鈥?user_id (BIGINT) - 绯荤粺鐢ㄦ埛ID锛堢櫥褰曡处鍙稩D锛夈€?
+鈥?assistant_no (STRING) - 鍔╂暀宸ュ彿銆?
+鈥?real_name (STRING) - 鍔╂暀濮撳悕銆?
+鈥?nickname (STRING) - 鍔╂暀鏄电О銆?
+鈥?gender (STRING) - 鎬у埆銆?
+鈥?mobile (STRING) - 鎵嬫満鍙枫€?
+鈥?status (STRING) - 鍦ㄨ亴鐘舵€侊紙鈥滃湪鑱屸€?鈥滅鑱屸€濈瓑锛夈€?
+鈥?visible_flag (TINYINT) - 鍓嶅彴鍙鏍囧織锛?灞曠ず/0闅愯棌锛夈€?
+鈥?skill_category (STRING) - 鏈嶅姟鎶€鑳界被鍒€傛瘮濡傗€滃熀纭€璇炬暀缁冣€濄€佲€滈珮绾ц鏁欑粌鈥濈瓑锛屽搴斿叾涓昏鏈嶅姟绫诲瀷銆?
+鈥?level (STRING) - 鍔╂暀绛夌骇銆?
+鈥?team_name (STRING) - 鎵€灞炲洟闃?鐝粍鍚嶇О銆?
+鈥?billing_mode (STRING) - 璁¤垂妯″紡锛堟寜灏忔椂/鎸夊満娆$瓑锛夈€?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+(鏉ユ簮: assistant_accounts_master瀛楁鏁寸悊锛屽墧闄や笉蹇呰瀛楁濡俿erial_number绛夈€俿tatus鐢辩爜琛ㄨ浆鎹负鏂囨湰銆俿kill_category鍙熀浜庡姪鏁欏叿澶囩殑鎶€鑳界被鍨嬬‘瀹氾紝渚嬪鑻ュ姪鏁欐湁鍩虹璇炬妧鑳藉垯鏍囦负鈥滃熀纭€璇炬暀缁冣€濓紱濡備竴涓姪鏁欒处鍙锋湁澶氱鏈嶅姟绫诲瀷锛屽彲浠ュ~鍐欎富瑕佺被鍨嬫垨鈥滃鎶€鑳解€濄€傚洟闃熷悕绉皌eam_name鑻DS娌℃湁鍙€氳繃assistant_team_id鍏宠仈TEAM缁磋〃鑾峰彇銆?
+DIM_ASSISTANT_TEAM锛堝姪鏁欏洟闃熺淮搴﹁〃锛?
+鎻忚堪锛?鍔╂暀鍥㈤槦/缁勭粐缁村害銆傚鏋滄湁灏嗗姪鏁欏垝鍒嗗洟闃熸垨閮ㄩ棬鐨勯渶姹傦紝鍒欏缓绔嬫缁磋〃銆傚綋鍓嶆暟鎹湁assistant_team_id浣嗘湭缁欏悕绉帮紝鍙悗缁ˉ鍏呫€?
+涓婚敭: team_id
+瀛楁:
+鈥?team_id (BIGINT) - 鍥㈤槦ID锛屼富閿€?
+鈥?team_name (STRING) - 鍥㈤槦鍚嶇О銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID/缁勭粐褰掑睘ID銆?
+鈥?remark (STRING) - 澶囨敞銆?
+(鏉ユ簮: 濡備笟鍔¢厤缃湁瀹氫箟鍥㈤槦锛屽垯濉叆銆傚綋鍓嶅彲浠巃ssistant_team_id涓嶅悓鍊兼灇涓惧~榛樿鍚嶇О锛屼緥濡傞兘灞炰簬鈥滄暀缁冪粍鈥濇殏鏃躲€傛缁村害鍦ㄦ暟鎹腑淇℃伅缂轰箯锛屽彲涓嶅己鍒朵娇鐢ㄣ€?
+DIM_PAY_METHOD锛堟敮浠樻柟寮忕淮搴﹁〃锛?
+鎻忚堪锛?鏀粯鏂瑰紡缁村害銆傜淮鎶ゆ敮浠樻笭閬撶紪鐮佷笌鍚嶇О鐨勫搴斿叧绯汇€傜敤浜庣炕璇戞敮浠樿褰曚腑鐨刾ay_method銆?
+涓婚敭: pay_method_code
+瀛楁:
+鈥?pay_method_code (INT) - 鏀粯鏂瑰紡浠g爜锛屼富閿€?
+鈥?pay_method_name (STRING) - 鏀粯鏂瑰紡鍚嶇О銆備緥濡傗€滅幇閲戔€濄€佲€滃井淇♀€濄€佲€滄敮浠樺疂鈥濄€佲€滃偍鍊煎崱鈥濄€?
+鈥?method_type (STRING) - 鏀粯绫诲瀷澶х被銆備緥濡傗€滅幇閲戠被鈥濄€佲€滅涓夋柟鏀粯鈥濄€佲€滀細鍛樿处鎴封€濈瓑鍒嗙被銆?
+鈥?remark (STRING) - 澶囨敞銆?
+(鏉ユ簮: 涓氬姟绯荤粺鏀粯鏂瑰紡閰嶇疆銆傜敱浜庡鍑烘暟鎹腑浠呭嚭鐜?绉峱ay_method浠g爜涓旀湭缁欐枃瀛楋紝闇€涓庝笟鍔$‘璁ょ紪鐮併€備緥濡傚父瑙佹槧灏勶細1=鐜伴噾,2=寰俊,3=鏀粯瀹?4=閾惰仈,5=鍌ㄥ€煎崱 绛夈€侲TL鍒濆鍖栨椂鍙牴鎹凡鐭ユ敮浠樻柟寮忓~鍏咃紝鍚庣画鑻ユ湁鏂版柟寮忛€氳繃閰嶇疆澧炶ˉ銆傛缁磋〃纭繚鍒嗘瀽鎶ヨ〃鏄剧ず鏀粯鏂瑰紡鏃剁敤鍚嶇О鑰岄潪浠g爜銆?
+DIM_ORDER_ASSISTANT_TYPE锛堝姪鏁欐湇鍔$被鍨嬬淮搴﹁〃锛?
+鎻忚堪锛?鍔╂暀鏈嶅姟绫诲瀷缁村害銆傛弿杩拌鍗曚腑鍔╂暀鏈嶅姟鐨勭被鍨嬬紪鐮佸惈涔夈€?
+涓婚敭: type_code
+瀛楁:
+鈥?type_code (INT) - 鍔╂暀鏈嶅姟绫诲瀷鐮侊紝涓婚敭銆?
+鈥?type_name (STRING) - 绫诲瀷鍚嶇О銆傚鈥滃熀纭€璇炬湇鍔♀€濄€佲€滈檮鍔犺鏈嶅姟鈥濄€?
+鈥?description (STRING) - 鎻忚堪璇存槑銆?
+(鏉ユ簮: 鐢变笟鍔¢厤缃垨鏁版嵁鎺ㄦ柇銆傛湰妗堜緥鏍规嵁鍔╂暀娴佹按涓嚭鐜扮殑1鍜?鎺ㄥ畾锛?=鍩虹鏈嶅姟锛?=闄勫姞鏈嶅姟銆傜淮琛ㄩ渶鐢变笟鍔$‘璁ゅ疄闄呭惈涔夊悗缁存姢銆?
+DIM_COUPON_PLATFORM锛堝埜骞冲彴缁村害琛級
+鎻忚堪锛?鍒告墍灞炲钩鍙扮淮搴︺€傛爣璇嗗洟璐埜鏉ユ簮鐨勫钩鍙帮紝渚嬪缇庡洟銆佸ぇ浼楃偣璇勭瓑銆傜敤浜庡垎鏋愬悇娓犻亾鍒镐娇鐢ㄦ儏鍐点€?
+涓婚敭: platform_code
+瀛楁:
+鈥?platform_code (STRING) - 骞冲彴浠g爜锛屼富閿€傚鈥淢T鈥濅唬琛ㄧ編鍥€?
+鈥?platform_name (STRING) - 骞冲彴鍚嶇О銆傚鈥滅編鍥⑩€濄€?
+鈥?company (STRING) - 骞冲彴鍏徃/鎵€灞為泦鍥€?
+鈥?remark (STRING) - 澶囨敞銆?
+(鏉ユ簮: 涓氬姟缁存姢銆傚彲棰勮甯歌鍥㈣喘骞冲彴銆侲TL鍙牴鎹埜dealId鎴朿ertificateId鏍煎紡鍒ゆ柇骞冲彴锛屽浠?鈥淢T鈥濆紑澶寸殑鍒哥爜褰掔被缇庡洟銆備负绋冲Ε璧疯搴斾汉宸ュ缓绔嬬淮琛紝platform_code鍙敤鎷奸煶缂╁啓鎴栬嫳鏂囥€?
+鍏朵粬缁村害璇存槑锛?
+闄や笂杩颁富瑕佺淮搴﹀锛屾暟鎹ā鍨嬭繕鍖呮嫭鏃堕棿缁村害锛圖IM_DATE 绛夛級鐢ㄤ簬鏃ユ湡鐨勫睘鎬у垎鏋愶紝姣忔棩鍙淮鎶や竴鏉¤嚜鐒舵棩鏈熻褰曪紝鍖呮嫭骞淬€佹湀銆佹棩銆佹槦鏈熴€佽妭鍋囨棩鏍囪瘑绛夛紝鐢ㄤ簬鎸夋棩缁熻锛堟湰娆℃湭璇﹀垪瀛楁锛夈€傜敱浜庤姹傛寜鑷劧鏃ユ眹鎬伙紝涓嶈€冭檻钀ヤ笟鏃舵鍒掑垎锛屽洜姝ゆ椂闂寸淮搴﹀彧闇€鎸夋棩鍘嗘棩绮掑害璁捐锛屾棤闇€闂叉椂/蹇欐椂绛夊睘鎬с€?
+3.2 鏄庣粏浜嬪疄琛ㄥ畾涔?
+FACT_SALE_ITEM锛堝晢鍝侀攢鍞槑缁嗕簨瀹炶〃锛?
+鎻忚堪锛?璁板綍鍟嗗搧閿€鍞殑鏈€缁嗙矑搴︽槑缁嗭紝姣忔潯璁板綍浠h〃璁㈠崟涓敭鍑虹殑涓€涓晢鍝侀」锛圫KU琛岋級銆傜矑搴︼細涓€浠跺晢鍝侀攢鍞褰曘€?
+涓婚敭: (order_trade_no, site_goods_id, sequence_no) 澶嶅悎閿紝鎴栫郴缁熷唴閮ㄧ敓鎴愮殑娴佹按ID銆?
+澶栭敭鍏宠仈: 鍏宠仈缁村害琛?DIM_SITE銆丏IM_PRODUCT銆丏IM_TABLE锛堣嫢闇€瑕佺煡閬撳湪鍝紶鍙版秷璐癸紝鍙€氳繃璁㈠崟鍏宠仈鍙拌垂琛ㄨ幏鍙栵紝涓嶇洿鎺ュ叧鑱攖able锛夈€丏IM_MEMBER锛堝鏋滆鍗曟湁鍏宠仈浼氬憳锛岄€氳繃璁㈠崟姹囨€诲彲鎷垮埌锛屼笉鐩存帴鍦ㄨ鍏宠仈锛夈€?
+瀛楁:
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+sale_item_id 鍟嗗搧閿€鍞槑缁咺D锛屼富閿?ods_store_sale_item.id
+order_trade_no 璁㈠崟浜ゆ槗鍙?ods_store_sale_item.order_trade_no
+order_settle_id 璁㈠崟缁撶畻ID ods_store_sale_item.order_settle_id
+site_id 闂ㄥ簵ID ods_store_sale_item.site_id
+site_goods_id 闂ㄥ簵鍟嗗搧ID ods_store_sale_item.site_goods_id
+goods_id 鍝佺墝鍟嗗搧ID ods_store_sale_item.goods_id锛坱enant_goods_id锛?
+goods_name 鍟嗗搧鍚嶇О锛堥攢鍞椂鍐椾綑锛?ods_store_sale_item.goods_name
+category_id 鍟嗗搧鍒嗙被ID ods_store_sale_item.category_id 鎴栭€氳繃 site_goods_id 鍏宠仈 ods_store_product 鍙?category_id
+quantity 閿€鍞暟閲?ods_store_sale_item.quantity
+unit_price 閿€鍞崟浠?ods_store_sale_item.unit_price
+discount_amount 鎶樻墸閲戦锛堜細鍛樻姌鎵?鎵嬪伐浼樻儬娣峰悎锛?ods_store_sale_item.discount_amount锛坉iscount_money锛?
+final_amount 瀹炴敹閲戦 浼樺厛鐢?ods_store_sale_item.actual_amount锛涘鏃狅紝鍒?unit_price * quantity - discount_amount
+is_gift 鏄惁璧犲搧 ods_store_sale_item.is_gift
+sale_time 閿€鍞椂闂?榛樿锛歰ds_store_sale_item.sales_time锛涘闇€缁熶竴浠ョ粨璐︽椂闂达紝鍙€氳繃 order_settle_id 鍏宠仈 ods_order_receipt_detail.settle_time 瑕嗙洊
+member_id 浼氬憳ID锛堢粺涓€浠庤鍗曠淮搴﹁幏鍙栵級 ods_order_receipt_detail.member_id锛堟寜 order_settle_id 鍏宠仈锛?
+salesman_id 鎺ㄩ攢鍛業D ods_store_sale_item.salesman_user_id
+operator_id 鎿嶄綔鍛業D ods_store_sale_item.operator_id
+is_refunded 鏄惁宸查€€娆撅紙鏍囪涓哄悗缁閫€娆剧殑閿€鍞級 鑻?ods_store_sale_item.is_refunded 瀛楁鏈夋晥鍒欑洿鎺ユ槧灏勶紝鍚﹀垯渚濇嵁 fact_refund 涓叧鑱旂殑 sale_item_id 琛嶇敓
+
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙凤紝鏍囪瘑灞炰簬鍝釜璁㈠崟銆?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID锛屼究浜庝笌缁撶畻/鏀粯鍏宠仈銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID锛屽叧鑱擠IM_SITE銆?
+鈥?goods_id (BIGINT) - 鍝佺墝鍟嗗搧ID锛屽叧鑱擠IM_PRODUCT.goods_id銆?
+鈥?site_goods_id (BIGINT) - 闂ㄥ簵鍟嗗搧ID锛屽叧鑱擠IM_PRODUCT锛堝彲閫氳繃璇D鎵惧埌鍟嗗搧锛屼篃鍙笉閲嶅瀛樺偍site_goods_id锛屽洜宸茶兘閫氳繃goods_id+site_id瀹氫綅锛岃繖閲屼繚鐣欐柟渚跨洿鎺ヨ繛鎺DS鍙傝€冿級銆?
+鈥?goods_name (STRING) - 鍟嗗搧鍚嶇О鍐椾綑銆?
+鈥?category_id (BIGINT) - 鍟嗗搧绫诲埆ID锛屽叧鑱擠IM_PRODUCT_CATEGORY锛岀敤浜庢柟渚挎寜绫诲埆缁熻銆?
+鈥?quantity (DECIMAL(10,2)) - 閿€鍞暟閲忋€?
+鈥?unit_price (DECIMAL(10,2)) - 鍘熷崟浠枫€傝鍟嗗搧鍘熶环锛堟湭鎶樻墸鏃剁殑鍗曚环锛夈€?
+鈥?discount_amount (DECIMAL(10,2)) - 鎶樻墸閲戦銆傝琛屽晢鍝佷韩鍙楃殑鎶樻墸鎬婚銆?
+鈥?final_amount (DECIMAL(10,2)) - 瀹炴敹閲戦銆? unit_price*quantity - discount_amount銆?
+鈥?is_gift (TINYINT) - 鏄惁璧犲搧鏍囧織銆?=璧犻€侊紝0=姝e父閿€鍞€傝禒鍝佺殑final_amount閫氬父涓?銆?
+鈥?sale_time (DATETIME) - 閿€鍞椂闂?璁㈠崟鏃堕棿銆傚彇璁㈠崟鐨勭粨璐︽椂闂存垨鍟嗗搧鍔犲叆璁㈠崟鏃堕棿銆傜敤浜庢棩绮掑害鍒嗘瀽銆?
+鈥?member_id (BIGINT) - 浼氬憳ID銆傝嫢璁㈠崟鏈変細鍛橈紝鍒欐椤瑰綊灞炶浼氬憳锛屽惁鍒欎负绌恒€?
+鈥?salesman_id (BIGINT) - 鎺ㄩ攢鍛業D銆傚鏈夋寚瀹氱殑閿€鍞汉鍛樸€?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆傚綍鍏ユ閿€鍞殑鏀堕摱鍛樸€?
+鏉ユ簮鍙婇€昏緫锛?鐢監DS_STORE_SALE_ITEM娓呮礂寰楀埌銆傜洿鎺ユ槧灏勫ぇ閮ㄥ垎瀛楁锛歲uantity, unit_price, discount_amount 鏉ヨ嚜ODS瀵瑰簲瀛楁锛沠inal_amount鍦∣DS涓彲璁$畻鎴栧凡鎻愪緵銆俶ember_id骞舵湭鐩存帴鍦∣DS閿€鍞涓嚭鐜帮紝浣嗚嫢璇ヨ鍗曠粦瀹氫細鍛橈紝鍒欓€氳繃璁㈠崟姹囨€诲叧鑱斿埌鎵€鏈夎锛孍TL鍙互鍦ㄥ姞杞芥椂濉叆鍚屼竴order_trade_no涓嬬殑member_id锛堣繖瑕佹眰ETL鍦ㄥ鐞嗚鍗曟椂鏈変細鍛樻槧灏勶級銆俿ale_time鍙彇璁㈠崟缁撹处鏃堕棿锛屼互渚挎墍鏈夎浣跨敤鍚屼竴缁撶畻鏃堕棿渚夸簬瀵归綈鏃ユ湡銆傝嫢鏈夐€€娆惧彂鐢燂紝fact_sale_item涓嶅垹闄ゅ師閿€鍞褰曪紝鑰屾槸鍦‵ACT_REFUND涓褰曢€€娆撅紝鎴栧彲澧炲姞涓€涓爣璁癷s_refunded銆傝繖閲屼繚鐣檌s_refund鏍囧織浠ヤ緵杩囨护閫€璐ч」锛屼絾閲戦涓嶈皟鏁达紝鍑€閿€鍞鐨勮绠楀皢鍦ㄦ眹鎬诲眰鑰冭檻閫€娆俱€?
+FACT_TABLE_USAGE锛堝彴璐逛娇鐢ㄦ槑缁嗕簨瀹炶〃锛?
+鎻忚堪: 璁板綍鍙版浣跨敤浜х敓鐨勫彴璐规槑缁嗐€傛瘡鏉¤褰曚唬琛ㄩ【瀹娇鐢ㄤ竴寮犲彴妗屼竴娆$殑鏀惰垂鎯呭喌銆傜矑搴︼細涓€绗斿彴璐硅处鍗曪紙閫氬父瀵瑰簲涓€涓鍗曠殑鍙拌垂閮ㄥ垎锛夈€?
+涓婚敭: id锛堝彴璐规祦姘碔D锛夈€?
+澶栭敭鍏宠仈: site_id鈫扗IM_SITE锛宻ite_table_id鈫扗IM_TABLE锛宮ember_id鈫扗IM_MEMBER锛堝閫傜敤锛夛紝assistant_id鏃犵洿鎺ュ叧鑱旇繖閲岋紝鍥犱负鍔╂暀鏀惰垂鐙珛璁板綍銆?
+瀛楁:
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+table_usage_id 鍙拌垂娴佹按ID锛屼富閿?table_fee_transactions_log.id
+order_trade_no 璁㈠崟浜ゆ槗鍙?table_fee_transactions_log.order_trade_no
+order_settle_id 璁㈠崟缁撶畻ID table_fee_transactions_log.order_settle_id
+site_id 闂ㄥ簵ID table_fee_transactions_log.site_id
+site_table_id 鍙版ID table_fee_transactions_log.site_table_id
+table_name 鍙版鍚嶇О table_fee_transactions_log.table_name
+start_time 寮€鍙版椂闂?table_fee_transactions_log.start_use_time
+end_time 绂诲彴鏃堕棿 table_fee_transactions_log.last_use_time
+duration_minutes 浣跨敤鏃堕暱锛堝垎閽燂級 鑻?real_table_use_seconds 鏈夊€硷細real_table_use_seconds / 60锛涘惁鍒欙細EXTRACT(EPOCH FROM (last_use_time - start_use_time))/60
+billing_unit_price 璁¤垂鍗曚环锛堝彲閫変繚鐣欙級 table_fee_transactions_log.billing_unit_price锛堝嵆 ledger_unit_price锛?
+鏁版嵁浠撳簱寤烘ā涓?ETL 瀵规帴 PRD
+billing_count 璁¤垂鏁伴噺锛堝彲閫変繚鐣欙級 table_fee_transactions_log.billing_count锛堝嵆 ledger_count锛?
+base_fee 鍙拌垂鍘熶环灏忚锛堟湭鎶樻墸锛?table_fee_transactions_log.ledger_amount
+member_discount 浼氬憳鎶樻墸閲戦 table_fee_transactions_log.member_discount_amount
+coupon_deduction 鍒告姷鎵i噾棰?table_fee_transactions_log.coupon_discount_amount锛坈oupon_promotion_amount锛?
+manual_discount 浜哄伐鍑忓厤閲戦 浼樺厛锛歰ds_table_use_log.manual_adjust_amount锛涘鏃狅紝鍒?危 ods_table_fee_adjust.adjust_amount锛堟寜 order_settle_id+site_table_id 姹囨€伙級
+鏁版嵁浠撳簱寤烘ā涓?ETL 瀵规帴 PRD
+service_fee 闄勫姞鏈嶅姟璐?绠$悊璐?table_fee_transactions_log.service_fee锛坢gmt_fee锛?
+final_table_fee 鍙拌垂瀹炴敹閲戦 浼樺厛鐢?table_fee_transactions_log.final_table_fee锛坮eal_table_charge_money锛夛紱濡傛棤锛屽垯 base_fee - member_discount - coupon_deduction - manual_discount + service_fee
+member_id 鍏宠仈浼氬憳ID锛堝彲绌猴級 table_fee_transactions_log.member_id
+operator_id 鎿嶄綔鍛業D table_fee_transactions_log.operator_id
+salesman_id 鎺ㄩ攢鍛業D锛堝鏈夛級 table_fee_transactions_log.salesman_user_id
+is_adjusted 鏄惁鍋氳繃浜哄伐璋冩暣锛?/1锛?CASE WHEN manual_discount > 0 THEN 1 ELSE 0 END
+is_canceled 鍙拌垂璁板綍鏄惁浣滃簾/鍒犻櫎锛?/1锛?CASE WHEN table_fee_transactions_log.is_deleted = 1 THEN 1 ELSE 0 END
+
+
+鈥?table_usage_id (BIGINT) - 鍙拌垂娴佹按ID锛團ACT涓婚敭锛屽搴擮DS_TABLE_USE_LOG.id锛夈€?
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+鈥?site_table_id (BIGINT) - 鍙版ID锛屽叧鑱擠IM_TABLE銆?
+鈥?table_name (STRING) - 鍙版鍚嶇О銆傚啑浣欐柟渚挎煡闃呫€?
+鈥?start_time (DATETIME) - 寮€鍙版椂闂淬€?
+鈥?end_time (DATETIME) - 绂诲彴鏃堕棿銆?
+鈥?duration_minutes (INT) - 浣跨敤鏃堕暱锛堝垎閽燂級銆傚彲鐢眘tart/end璁$畻鎴栫洿鎺ュ彇ODS real_table_use_seconds鎹㈢畻銆?
+鈥?base_fee (DECIMAL(10,2)) - 鍘熷彴璐归噾棰濓紙鏈墸鍑忓墠璐圭敤锛夈€?
+鈥?member_discount (DECIMAL(10,2)) - 浼氬憳鎶樻墸鍑忓厤閲戦銆?
+鈥?coupon_deduction (DECIMAL(10,2)) - 鍒告姷鎵i噾棰濄€?
+鈥?manual_discount (DECIMAL(10,2)) - 鎵嬪伐鍑忓厤璐圭敤銆?
+鈥?service_fee (DECIMAL(10,2)) - 闄勫姞鏈嶅姟璐广€?
+鈥?final_table_fee (DECIMAL(10,2)) - 瀹炴敹鍙拌垂閲戦銆? base_fee + service_fee - member_discount - coupon_deduction - manual_discount銆?
+鈥?member_id (BIGINT) - 浼氬憳ID锛堝鏋滆寮€鍙扮粦瀹氫細鍛橈級銆?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D锛堝紑鍙?缁撹处缁忓姙浜猴級銆?
+鈥?salesman_id (BIGINT) - 钀ラ攢鍛業D锛堝鏋滄湁鍦ㄥ満鏈嶅姟鍛橈級銆?
+鈥?is_adjusted (TINYINT) - 鏄惁鏈変汉宸ヨ皟鏁淬€?琛ㄧず鏈夋墜宸ユ墦鎶橈紙manual_discount>0锛夛紝0鏃犮€?
+鈥?is_canceled (TINYINT) - 鏄惁浣滃簾銆?琛ㄧず姝ゅ彴璐硅褰曡鍙栨秷鏈敹璐癸紙鐢变簬璁㈠崟鍙栨秷绛夛級锛?姝e父銆?
+
+
+
+鏉ユ簮鍙婇€昏緫锛?鐢監DS_TABLE_USE_LOG鐩存帴鏁寸悊銆俠ase_fee瀵瑰簲ODS鐨刲edger_amount锛宮ember_discount, coupon_deduction, manual_discount, service_fee鐩存帴鏉ヨ嚜鍚屽悕瀛楁锛宖inal_table_fee鍙朞DS.real_table_charge_money鏍¢獙璁$畻銆俰s_adjusted鏍囧織=1褰搈anual_discount>0鎴朼djust_amount鏈夊€笺€俰s_canceled鍙牴鎹甇DS.is_delete鎴栬鍗曞彇娑堟儏鍐佃瀹氾紙鑻ヨ鍗曟湭缁撶畻瀵艰嚧姝よ褰曟棤鏁堬級銆傛敞鎰忥細 manual_discount鏉ヨ嚜鍗曠嫭鐨凮DS_TABLE_FEE_ADJUST璁板綍锛屽鏋淥DS_USE_LOG閲屽凡鏈塧djust_amount瀛楁锛屽垯ETL闇€瑕佷笌璋冩暣琛ㄦ牳瀵圭‘淇濅竴鑷淬€傛墍鏈夐噾棰濆瓧娈靛崟浣嶅潎涓哄厓銆侳ACT_TABLE_USAGE涓鸿鍗曟眹鎬绘椂鍙拌垂鎬婚鐨勬潵婧愩€?
+FACT_ASSISTANT_SERVICE锛堝姪鏁欐湇鍔℃槑缁嗕簨瀹炶〃锛?
+鎻忚堪: 璁板綍鍔╂暀鏈嶅姟/鏁欑粌闄粌鐨勬槑缁嗐€傛瘡鏉¤褰曞搴旈【瀹韩鍙楃殑涓€娆″姪鏁欐湇鍔°€傜矑搴︼細涓€鏉″姪鏁欐湇鍔¤褰曘€?
+涓婚敭: id锛堝姪鏁欐祦姘碔D锛夈€?
+澶栭敭鍏宠仈: site_id鈫扗IM_SITE锛宎ssistant_id鈫扗IM_ASSISTANT锛宮ember_id鈫扗IM_MEMBER锛宻ite_table_id鈫扗IM_TABLE锛堝鍒嗘瀽闇€瑕侊紝鍙繚鐣欏瓧娈典絾涓嶄竴瀹氬己鍏宠仈锛夛紝service_type鈫扗IM_ORDER_ASSISTANT_TYPE銆?
+瀛楁:
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+assistant_service_id 鍔╂暀鏈嶅姟娴佹按ID锛屼富閿?ods_assistant_service_log.id
+order_trade_no 璁㈠崟浜ゆ槗鍙?ods_assistant_service_log.order_trade_no
+order_settle_id 璁㈠崟缁撶畻ID ods_assistant_service_log.order_settle_id
+site_id 闂ㄥ簵ID ods_assistant_service_log.site_id
+site_assistant_id 闂ㄥ簵鍔╂暀璐﹀彿ID ods_assistant_service_log.site_assistant_id
+assistant_name 鍔╂暀鍚嶇О鍐椾綑 ods_assistant_service_log.assistant_name 鎴栧叧鑱?assistant_accounts_master.real_name/nickname
+member_id 浼氬憳ID ods_assistant_service_log.member_id
+service_start_time 鏈嶅姟寮€濮嬫椂闂?ods_assistant_service_log.start_time
+service_end_time 鏈嶅姟缁撴潫鏃堕棿 ods_assistant_service_log.end_time
+service_duration_minutes 鏈嶅姟鏃堕暱锛堝垎閽燂級 鑻?ODS 鏈夋€荤鏁板瓧娈碉細seconds/60锛涘惁鍒?EXTRACT(EPOCH FROM (end_time - start_time))/60
+service_type_id 鍔╂暀鏈嶅姟绫诲瀷锛堝熀纭€璇?闄勫姞璇剧瓑锛?ods_assistant_service_log.service_type锛堝湪 DWD 鍏宠仈 dim_order_assist_type 杞箟锛?
+base_fee 鍔╂暀鍩虹璇?鍗曚环璁¤垂閲戦锛堝師浠凤級 ods_assistant_service_log.base_fee锛屾垨鎸夊崟浠访楁椂闀胯绠楋紙瑙佹牱鏈瓧娈碉級
+member_discount 鍔╂暀鏈嶅姟浼氬憳鎶樻墸閲戦 ods_assistant_service_log.member_discount_amount
+manual_discount 鍔╂暀鏈嶅姟浜哄伐鎶樻墸閲戦 ods_assistant_service_log.manual_discount_amount
+coupon_deduction 鍒告姷鎵i噾棰濓紙濡傚洟璐埜鍒嗘憡鍒板姪鏁欙級 鑻?ODS 鏈夊搴斿瓧娈靛垯鐩存帴鏄犲皠锛涜嫢鏃犲垯榛樿 0锛岀敱 fact_coupon_usage 涓嶅啀鍒嗘憡鍒板姪鏁?
+final_service_fee 鍔╂暀鏈嶅姟瀹炴敹閲戦 浼樺厛锛歰ds_assistant_service_log.final_service_fee锛涘惁鍒?base_fee - member_discount - manual_discount - coupon_deduction
+operator_id 鎿嶄綔鍛業D ods_assistant_service_log.operator_id
+salesman_id 鎺ㄩ攢鍛業D ods_assistant_service_log.salesman_user_id锛堝鏈夛級
+is_canceled 璇ユ潯鍔╂暀鏈嶅姟鏄惁琚€滃簾闄も€?CASE WHEN (ods_assistant_service_log.is_trash = 1 OR 鍦?ods_assistant_cancel_log 鏈夊尮閰嶈褰? THEN 1 ELSE 0 END
+鏁版嵁浠撳簱寤烘ā涓?ETL 瀵规帴 PRD
+cancel_reason 搴熼櫎鍘熷洜 鑻ュ瓨鍦?ods_assistant_cancel_log 璁板綍锛屽垯鍙栧叾 reason锛涘惁鍒欎负绌?
+service_score 鏈嶅姟璇勫垎 ods_assistant_service_log.service_grade
+skill_score 鎶€鑳借瘎鍒?ods_assistant_service_log.skill_grade
+overall_score 缁煎悎璇勫垎 ods_assistant_service_log.sum_grade
+
+鈥?assistant_service_id (BIGINT) - 鍔╂暀鏈嶅姟娴佹按ID锛堜富閿級銆?
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+鈥?site_table_id (BIGINT) - 鍙版ID锛堝姪鏁欐湇鍔″彂鐢熺殑鍙版锛夈€?
+鈥?assistant_id (BIGINT) - 鍔╂暀ID锛屽叧鑱擠IM_ASSISTANT銆?
+鈥?assistant_name (STRING) - 鍔╂暀濮撳悕鍐椾綑銆?
+鈥?service_type (INT) - 鍔╂暀鏈嶅姟绫诲瀷浠g爜锛屽叧鑱擠IM_ORDER_ASSISTANT_TYPE鑾峰彇绫诲瀷鍚嶇О銆?
+鈥?start_time (DATETIME) - 鏈嶅姟寮€濮嬫椂闂淬€?
+鈥?end_time (DATETIME) - 鏈嶅姟缁撴潫鏃堕棿銆?
+鈥?duration_minutes (INT) - 鏈嶅姟鏃堕暱锛堝垎閽燂級銆?
+鈥?base_fee (DECIMAL(10,2)) - 鍘熸湇鍔¢噾棰濄€?
+鈥?member_discount (DECIMAL(10,2)) - 浼氬憳鎶樻墸閲戦銆?
+鈥?coupon_deduction (DECIMAL(10,2)) - 鍒告姷鎵i噾棰濄€?
+鈥?manual_discount (DECIMAL(10,2)) - 鎵嬪伐鍑忓厤閲戦銆?
+鈥?final_fee (DECIMAL(10,2)) - 瀹炴敹鏈嶅姟璐归噾棰濄€? base_fee - 鍚勭被鎶樻墸鍑忓厤銆?
+鈥?member_id (BIGINT) - 浼氬憳ID锛堜韩鍙楁湇鍔$殑椤惧锛屽鏈変細鍛樼粦瀹氾級銆?
+鈥?is_canceled (TINYINT) - 鏄惁琚彇娑堛€?琛ㄧず璇ユ湇鍔″疄闄呮湭瀹屾垚锛堣搴熼櫎锛夛紝0姝e父瀹屾垚銆?
+鈥?cancel_reason (STRING) - 鍙栨秷鍘熷洜鎻忚堪锛堝鏈夛級銆?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D锛堝綍鍏?纭姝ゆ湇鍔$殑鍛樺伐锛夈€?
+鈥?salesman_id (BIGINT) - 鎺ㄩ攢鍛業D锛堝鏈夎惀閿€浜哄憳淇冩垚姝ゆ湇鍔★級銆?
+鈥?service_score (INT) - 鏈嶅姟璇勫垎锛堥【瀹㈠鏈嶅姟鎬佸害鐨勮瘎鍒嗭級銆?
+鈥?skill_score (INT) - 鎶€鑳借瘎鍒嗐€?
+鈥?overall_score (INT) - 缁煎悎璇勫垎銆?
+鈥?score_time (DATETIME) - 璇勪环鏃堕棿銆?
+鏉ユ簮鍙婇€昏緫锛?鐢監DS_ASSISTANT_SERVICE_LOG鏁寸悊銆傚ぇ閮ㄥ垎瀛楁鐩存帴鏄犲皠锛歜ase_fee=ledger_amount, member_discount/manual_discount/coupon_deduction鏉ユ簮瀵瑰簲瀛楁锛宖inal_fee=service_money銆俤uration璁$畻绉掓暟杞崲鍒嗛挓銆俿ervice_type浠DS.order_assistant_type濉厖銆俰s_canceled鍩轰簬ODS.is_trash鍒ゆ柇锛屽涓?鍒欐湰璁板綍鍦ㄤ笟鍔′笂琚彇娑堬紝涓嶈鍏ユ渶缁堟敹璐癸紙final_fee搴旇涓?鎴栧拷鐣ワ級銆傚浜庡彇娑堣褰曪紝鍙繘涓€姝ュ弬鑰僌DS_ASSISTANT_CANCEL_LOG浠ヨ幏鍙朿ancel_reason绛夛紝鍦‥TL涓€氳繃order_trade_no鍜宎ssistant_id鍖归厤灏嗗師鍥犲~鍏ャ€傝瘎鍒嗗瓧娈电洿鎺ュ彇ODS涓殑service_grade/skill_grade/sum_grade锛屽鏈夌殑璇濄€傛敞鎰忥細 宸插彇娑堢殑鍔╂暀鏈嶅姟涓嶅簲璁″叆璁㈠崟瀹為檯鏀嚭锛屽洜姝ゅ湪姹囨€绘椂搴旀帓闄ゆ垨final_fee=0銆侳ACT_ASSISTANT_SERVICE涓鸿鍗曟眹鎬诲眰鍔╂暀璐归儴鍒嗘潵婧愶紝涔熺敤浜庝汉鍔涚哗鏁堢粺璁★紙濡傚崟涓姪鏁欐湇鍔℃鏁般€佽瘎鍒嗭級銆?
+
+搴熼櫎璁¤垂閫昏緫涓庢淳鐢熷瓧娈碉紙鏂板锛?
+鍦?DWD 灞傦紝鎴戜滑灏?ODS 鍔╂暀娴佹按涓殑鏃堕棿涓庨噾棰濆瓧娈垫爣鍑嗗寲涓轰互涓嬫牳蹇冩寚鏍囷紙瀛楁鍚嶄互鏈簨瀹炶〃瀹為檯鍛藉悕涓哄噯锛夛細
+鈥?service_duration_sec锛氭湇鍔″疄闄呭彂鐢熸椂闀匡紙绉掞級锛屾潵婧愪簬 ODS real_use_seconds銆?
+鈥?charge_duration_sec锛氳璐规椂闀匡紙绉掞級锛屾潵婧愪簬 ODS income_seconds銆?
+鈥?base_fee锛氬師濮嬪簲鏀堕噾棰濓紝鏉ユ簮浜?ODS ledger_amount銆?
+鈥?final_fee锛氭湰鏉℃湇鍔℃渶缁堣鍏ヨ惀鏀剁殑閲戦锛屾潵婧愪簬 ODS projected_income / service_money銆?
+鈥?is_canceled锛氭槸鍚﹀簾闄ゆ爣蹇楋紝鏉ユ簮浜?ODS is_trash銆?
+DWD 灞傜粺涓€绾﹀畾锛?
+1. 鏀跺叆缁熻鍙e緞锛?
+o 鎵€鏈夆€滃姪鏁欐敹鍏モ€濈被鎸囨爣锛岀粺涓€浣跨敤 final_fee 浣滀负璁℃敹鍏ュ彛寰勩€?
+o 涓嶅啀鐩存帴浣跨敤 base_fee 姹囨€伙紝浠ラ伩鍏嶅皢搴熼櫎鐨勬湭璁¤垂閮ㄥ垎绠楀叆鏀跺叆銆?
+2. 搴熼櫎鏈嶅姟鐨勫鐞嗭細
+o is_canceled = 1 鐨勮褰曚粛淇濈暀鍦ㄤ簨瀹炶〃涓紝鐢ㄤ簬鍒嗘瀽鈥滆搴熼櫎鐨勬湇鍔℃暟閲?/ 鏃堕暱 / 鍘熷閲戦鈥濄€?
+o 鍦ㄢ€滆惀鏀剁被鎶ヨ〃鈥濅腑锛岃嫢涓嶇壒鍒鏄庯紝缁熶竴鎸?final_fee 姹囨€伙紝鍥犳搴熼櫎鏈嶅姟涓湭璁¤垂閮ㄥ垎涓嶄細杩涘叆钀ヤ笟鏀跺叆銆?
+o 濡傞渶缁熻鈥滃簾闄ゅ鑷寸殑鏀跺叆鎹熷け鈥濓紝鍒欏彲浣跨敤锛歭ost_fee = base_fee - final_fee锛堜粎瀵?is_canceled = 1 鐨勮褰曠粺璁★級銆?
+3. 鏈嶅姟鏃堕暱鐩稿叧鍒嗘瀽锛?
+o 瀹為檯鏈嶅姟鎶曞叆浜哄姏鏃堕暱浣跨敤 service_duration_sec锛?
+o 鍙璐规椂闀夸娇鐢?charge_duration_sec锛?
+o 涓よ€呭樊鍊?service_duration_sec - charge_duration_sec 鍙敤浜庤 閲忊€滈潪璁¤垂鎶曞叆鈥濓紙渚嬪鍏嶈垂鏈嶅姟銆佹姇璇夎ˉ鍋跨瓑锛夈€?
+
+
+FACT_COUPON_USAGE锛堝洟璐埜浣跨敤鏄庣粏浜嬪疄琛級
+鎻忚堪: 璁板綍鍥㈣喘浼樻儬鍒革紙鍥㈣喘濂楅鍒革級鐨勪娇鐢ㄦ儏鍐点€傛瘡鏉¤褰曚唬琛ㄤ竴寮犲埜琚娇鐢ㄤ竴娆★紙鏍搁攢锛夈€傜矑搴︼細涓€娆″洟璐埜鏍搁攢浜嬩欢銆?
+涓婚敭: id锛堝埜浣跨敤娴佹按ID锛夈€?
+澶栭敭鍏宠仈: site_id鈫扗IM_SITE锛宲ackage_id鈫扗IM_GROUP_PACKAGE锛堥渶鍦―WD寤虹珛鍥㈣喘濂楅缁村害锛夛紝platform_code鈫扗IM_COUPON_PLATFORM銆?
+瀛楁:
+
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+coupon_usage_id 鍥㈣喘鍒镐娇鐢ㄦ祦姘碔D group_buy_packages_log.id
+order_trade_no 璁㈠崟浜ゆ槗鍙?group_buy_packages_log.order_trade_no
+order_settle_id 璁㈠崟缁撶畻ID group_buy_packages_log.order_settle_id
+site_id 闂ㄥ簵ID group_buy_packages_log.site_id
+coupon_code 鍒哥爜/鏍搁攢鐮?ods_platform_coupon_log.coupon_code 鎴?verify_code锛堟寜瀹為檯瀛楁锛?
+coupon_platform_id 鍒稿钩鍙癐D锛堢編鍥?鐐硅瘎绛夛級 ods_platform_coupon_log.platform_id锛堝湪 DWD 鍏宠仈 dim_coupon_platform锛?
+group_package_id 鍥㈣喘濂楅瀹氫箟ID group_buy_packages_log.group_package_id
+group_package_name 鍥㈣喘濂楅鍚嶇О group_buy_packages.group_package_name锛堥€氳繃 ID 鍏宠仈锛?
+coupon_face_value 鍒告爣绉板師浠凤紙甯傚満浠凤級 group_buy_packages.face_value 鎴栧钩鍙拌褰曚腑鐨?original_price
+coupon_settle_price 鍒哥粨绠椾环锛堥棬搴楀疄闄呬粠骞冲彴鏀跺埌鐨勯噾棰濓級 ods_platform_coupon_log.settle_price
+deduct_amount 鏈鏍搁攢鎶垫墸鍒拌鍗曠殑閲戦锛堢敤浜庤鍗曡璐︽祦姘达級 涓€鑸瓑浜?coupon_settle_price锛涘鏈夊樊棰濓紙渚嬪澶氬埜鍙犲姞锛夊彲鍙?group_buy_packages_log.deduct_amount
+verify_time 鏍搁攢鏃堕棿 ods_platform_coupon_log.verify_time
+member_id 缁戝畾浼氬憳ID锛堝鏈夛級 鑻ュ埜鏍搁攢涓庝細鍛樼粦瀹氾紝鍒欏彇 group_buy_packages_log.member_id锛涙棤鍒欎负绌?
+
+鈥?coupon_usage_id (BIGINT) - 鍒镐娇鐢ㄨ褰旾D锛堜富閿級銆?
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+鈥?site_table_id (BIGINT) - 鍙版ID锛堝埜瀵瑰簲鐨勫彴妗屾秷璐癸級銆?
+鈥?assistant_id (BIGINT) - 鍔╂暀ID锛堝鍒稿寘鍚姪鏁欐湇鍔★紝鍙褰曞叧鑱旓紝鍚﹀垯涓虹┖锛夈€?
+鈥?package_id (BIGINT) - 濂楅ID锛屽叧鑱擠IM_GROUP_PACKAGE銆?
+鈥?package_name (STRING) - 濂楅鍚嶇О鍐椾綑銆?
+鈥?platform_code (STRING) - 鍒告潵婧愬钩鍙颁唬鐮侊紝鍏宠仈DIM_COUPON_PLATFORM鑾峰緱鍚嶇О銆?
+鈥?coupon_code (STRING) - 鍒哥爜缂栧彿銆?
+鈥?deduct_amount (DECIMAL(10,2)) - 鎶垫墸閲戦銆傝鍒告牳閿€鎶垫墸鐨勯噾棰濅环鍊笺€?
+鈥?used_time (DATETIME) - 鍒镐娇鐢ㄦ椂闂淬€?
+鈥?operator_id (BIGINT) - 鏍搁攢鎿嶄綔鍛業D銆?
+鈥?salesman_id (BIGINT) - 閿€鍞憳ID锛堝鏋滄湁锛夈€?
+鈥?status (STRING) - 鍒镐娇鐢ㄧ姸鎬侊紙閫氬父涓衡€滃凡浣跨敤鈥濓紝濡傛湁闇€瑕佸彲鏍囪瘑寮傚父锛夈€?
+鏉ユ簮鍙婇€昏緫锛?缁煎悎group_buy_packages_LOG鍜孫DS_PLATFORM_COUPON_LOG鐨勬暟鎹€傝€冭檻鍒颁竴寮犲埜浣跨敤浼氬湪涓ゅ紶琛ㄥ悇鏈変竴鏉¤褰曪紝DWD灞傚彲灏嗕袱鑰呭悎骞讹細浠DS_GROUP_PACKAGE_LOG涓轰富锛屽洜涓哄畠鍖呭惈鎶垫墸閲戦绛夐棬搴楀唴閮ㄤ俊鎭紝琛ュ厖骞冲彴淇℃伅锛坧latform_code, coupon_code绛変粠ODS_PLATFORM_COUPON_LOG鑾峰彇锛夈€傚悎骞堕€昏緫锛氬尮閰嶆潯浠跺彲浠ユ槸璁㈠崟鍙?鍒窱D鎴栧埜鐮併€傜敱浜巆oupon_code鍦∣DS_GROUP_PACKAGE_LOG鏈繀鏈夛紝鑰屽湪骞冲彴琛ㄦ湁certificateId锛岄渶瑕侀€氳繃deal_id鎴杘rder鍏宠仈鏍稿銆傚鏋滃尮閰嶅洶闅撅紝涔熷彲涓嶅悎骞讹紝涓ゅ紶浜嬪疄琛ㄥ垎鍒缓锛涗絾涓烘柟渚垮垎鏋愶紝鍚堝苟鎴愪竴寮燜ACT_COUPON_USAGE鍖呭惈涓昏瀛楁銆俤educt_amount鐩存帴鍙栧椁愭祦姘寸殑deduct_money锛沺latform_code閫氳繃骞冲彴琛ㄦ垨deal_id鏄犲皠锛沜oupon_code鍙杙latform琛ㄧ殑certificateId锛堝埜鐮侊級銆傚鏋滄湁鏈尮閰嶇殑骞冲彴鍒歌褰曪紝涔熷彲鐙珛鍒嗘瀽锛屾澶勪互涓氬姟鎴愬姛浣跨敤涓轰富銆侳ACT_COUPON_USAGE鐨刣educt_amount浼氬弬涓庤鍗曟眹鎬荤殑浼樻儬鎬婚璁$畻锛屼篃鍙敤浜庣粺璁″洟璐础鐚敹鍏ャ€?
+FACT_PAYMENT锛堟敮浠樹簨瀹炶〃锛?
+鎻忚堪: 璁板綍璁㈠崟鐨勬敹娆炬槑缁嗭紝姣忔潯璁板綍浠h〃搴楀唴鏀跺埌涓€绗旀椤广€備笌payment_transactions涓€鑷达紝浣嗗湪DWD灞傚皢鏀粯鏂瑰紡浠g爜杞瘧锛屽叧鑱旇鍗曠瓑銆傜矑搴︼細涓€绗旀敮浠樻祦姘淬€?
+涓婚敭: id锛堟敮浠樻祦姘碔D锛夈€?
+澶栭敭鍏宠仈: site_id鈫扗IM_SITE锛宲ay_method_code鈫扗IM_PAY_METHOD锛宮ember_id鈫扗IM_MEMBER锛堝鏀粯鏂瑰紡涓哄偍鍊煎崱鎵f锛屽彲鍏宠仈瀵瑰簲浼氬憳锛夈€?
+瀛楁:
+
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+payment_id 鏀粯娴佹按ID锛屼富閿?payment_transactions.id
+order_trade_no 璁㈠崟浜ゆ槗鍙?payment_transactions.order_trade_no
+order_settle_id 璁㈠崟缁撶畻ID payment_transactions.order_settle_id
+site_id 闂ㄥ簵ID payment_transactions.site_id
+member_id 浼氬憳ID锛堝鏀粯涓庝細鍛樼粦瀹氾級 payment_transactions.member_id
+pay_method_code 鏀粯鏂瑰紡缂栫爜锛堢幇閲?寰俊/鍌ㄥ€煎崱绛夛級 payment_transactions.pay_type锛堝湪 DWD 鍏宠仈 dim_pay_method锛?
+pay_amount 鏀粯閲戦 payment_transactions.amount
+pay_time 鏀粯鏃堕棿 payment_transactions.pay_time
+transaction_id 绗笁鏂逛氦鏄撴祦姘村彿 payment_transactions.third_transaction_id锛堟寜瀹為檯瀛楁锛?
+operator_id 鎿嶄綔鍛業D payment_transactions.operator_id
+remark 澶囨敞 payment_transactions.remark
+
+鈥?payment_id (BIGINT) - 鏀粯娴佹按ID锛堜富閿級銆?
+鈥?order_trade_no (BIGINT) - 璁㈠崟浜ゆ槗鍙枫€?
+鈥?order_settle_id (BIGINT) - 璁㈠崟缁撶畻ID銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+鈥?pay_method_code (INT) - 鏀粯鏂瑰紡浠g爜锛屽叧鑱擠IM_PAY_METHOD鑾峰彇鍚嶇О銆?
+鈥?pay_method_name (STRING) - 鏀粯鏂瑰紡鍚嶇О鍐椾綑銆?
+鈥?pay_amount (DECIMAL(10,2)) - 鏀粯閲戦锛堟鍊硷紝鍏冿級銆?
+鈥?pay_time (DATETIME) - 鏀粯瀹屾垚鏃堕棿銆?
+鈥?transaction_id (STRING) - 绗笁鏂规敮浠樻祦姘村彿銆?
+鈥?member_id (BIGINT) - 浼氬憳ID锛堝鏋滄槸鍌ㄥ€煎崱鏀粯锛屾澶勮褰曚細鍛樿处鍙凤紝鍚﹀垯涓虹┖锛夈€?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D锛堟敹娆炬敹閾跺憳锛夈€?
+鏉ユ簮鍙婇€昏緫锛?鐩存帴鏉ユ簮payment_transactions娓呮礂銆俻ay_method_code鏇挎崲鍘熸湁鏀粯鏂瑰紡瀛楁锛宲ay_method_name鍙€氳繃缁磋〃濉叆鎴栫洿鎺ヤ繚鐣橭DS涓殑鏂囨湰銆俶ember_id涓€鑸笉鍦ㄦ敮浠樿褰曞嚭鐜帮紝浣嗗綋鏀粯鏂瑰紡鏄€滃偍鍊煎崱鈥濇椂锛屽彲浠ユ帹瀵煎搴斿摢涓細鍛橈細鏀粯璁板綍鏈韩鎴栬鍗曟湁浼氬憳鍏宠仈銆侲TL鍙互鍦ㄩ亣鍒板偍鍊煎崱鏀粯锛堜緥濡俻ay_method_code=5鍌ㄥ€煎崱锛夋椂锛屽皢璇ヨ鍗曠殑member_id濉厖姝ゅ瓧娈碉紝琛ㄧず杩欑瑪鏀粯浠庤浼氬憳璐︽埛鎵f銆傚叾浠栨敮浠樻柟寮忓垯member_id鐣欑┖銆侳ACT_PAYMENT鏁版嵁鐢ㄤ簬鍒嗘瀽浠樻鏂瑰紡鍗犳瘮锛屼篃鐢ㄤ簬璁㈠崟姹囨€昏绠楀疄鏀堕噾棰濇牎楠屻€?
+FACT_REFUND锛堥€€娆句簨瀹炶〃锛?
+鎻忚堪: 璁板綍閫€娆句氦鏄撴槑缁嗭紝姣忔潯璁板綍浠h〃搴楅噷閫€鍑轰竴绗旀缁欓【瀹€備笌refund_transactions瀵瑰簲銆傜矑搴︼細涓€绗旈€€娆炬祦姘淬€?
+涓婚敭: id锛堥€€娆炬祦姘碔D锛夈€?
+澶栭敭鍏宠仈: site_id鈫扗IM_SITE锛宲ay_method_code鈫扗IM_PAY_METHOD銆?
+瀛楁:
+
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+refund_id 閫€娆炬祦姘碔D锛屼富閿?refund_transactions.id
+order_trade_no 鍘熻鍗曚氦鏄撳彿 refund_transactions.order_trade_no
+order_settle_id 鍘熻鍗曠粨绠桰D refund_transactions.order_settle_id
+site_id 闂ㄥ簵ID refund_transactions.site_id
+member_id 浼氬憳ID refund_transactions.member_id
+refund_amount 閫€娆鹃噾棰?refund_transactions.amount
+pay_method_code 鍘熸敮浠樻柟寮忕紪鐮?refund_transactions.pay_type
+refund_time 閫€娆炬椂闂?refund_transactions.refund_time
+operator_id 鎿嶄綔鍛業D refund_transactions.operator_id
+reason 閫€娆惧師鍥?refund_transactions.reason
+related_payment_id 鍏宠仈鏀粯娴佹按ID锛堝鏈夛級 refund_transactions.payment_id 鎴栭€氳繃绗笁鏂规祦姘村彿鍖归厤
+
+
+鈥?refund_id (BIGINT) - 閫€娆炬祦姘碔D锛堜富閿級銆?
+鈥?order_trade_no (BIGINT) - 鍘熻鍗曚氦鏄撳彿銆?
+鈥?order_settle_id (BIGINT) - 鍘熻鍗曠粨绠桰D銆?
+鈥?site_id (BIGINT) - 闂ㄥ簵ID銆?
+鈥?pay_method_code (INT) - 閫€娆炬笭閬撲唬鐮侊紝鍏宠仈DIM_PAY_METHOD銆?
+鈥?pay_method_name (STRING) - 閫€娆炬笭閬撳悕绉板啑浣欍€?
+鈥?refund_amount (DECIMAL(10,2)) - 閫€娆鹃噾棰濓紙姝e€艰〃绀洪€€杩樼粰椤惧鐨勯挶锛屽厓锛夈€?
+鈥?refund_time (DATETIME) - 閫€娆炬椂闂淬€?
+鈥?original_payment_id (BIGINT) - 鍘熸敮浠樻祦姘碔D銆?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D锛堟墽琛岄€€娆剧殑鍛樺伐锛夈€?
+鏉ユ簮鍙婇€昏緫锛?鐢監DS_REFUND_RECORD娓呮礂銆俽efund_amount鍙栫粷瀵瑰€硷紙鍥犱负ODS鍙兘瀛樹负璐熷€硷紝鎴戜滑鍦╢act涓敤姝e€煎瓧娈佃〃绀洪€€杩橀噾棰濓紝浣嗗湪姹囨€昏绠楁椂浼氫綔涓哄噺椤癸級銆俻ay_method_code璇戠爜锛屽悓鏀粯鏂瑰紡缁磋〃銆俹riginal_payment_id鍙敤浜庡叧鑱旀壘鍑烘槸鍝瑪鏀粯琚€€锛堜絾鍒嗘瀽鐢ㄥ涓嶅ぇ锛屽彲閫変繚鐣欙級銆侳ACT_REFUND涓昏鐢ㄤ簬璐㈠姟鏍稿鍜岃绠楀噣鏀跺叆=鏀舵-閫€娆俱€傚璁㈠崟姹囨€荤殑褰卞搷鍦ㄤ簬濡傛灉鏌愯鍗曞綋鍦洪€€娆撅紝DWS璁㈠崟姹囨€诲彲鍑忓幓閫€娆鹃锛涘鏋滈€€娆惧彂鐢熷湪涓嶅悓鏃ュ垯瑙嗗垎鏋愬彛寰勫喅瀹氬浣曞鐞嗐€?
+FACT_BALANCE_CHANGE锛堜綑棰濆彉鍔ㄤ簨瀹炶〃锛?
+鎻忚堪: 璁板綍浼氬憳鍌ㄥ€间綑棰濈殑姣忔鍙樺姩鏄庣粏銆傛瘡鏉¤褰曞搴斾綑棰濆鍑忎簨浠躲€備笌member_balance_changes绫讳技锛屼絾杩涜娓呮礂鍜屽叧鑱斻€傜矑搴︼細涓€娆′綑棰濆彉鍔ㄣ€?
+涓婚敭: id锛堜綑棰濆彉鍔↖D锛夈€?
+澶栭敭鍏宠仈: member_id鈫扗IM_MEMBER锛宻ite_id鈫扗IM_SITE锛宑hange_type鈫扗IM_BALANCE_CHANGE_TYPE锛堝鏋滈渶瑕侊紝瀵圭被鍨嬭繘琛屾弿杩版槧灏勶級銆?
+瀛楁:
+
+DWD 瀛楁鍚?涓氬姟鍚箟 鏉ユ簮 ODS 瀛楁 / 璁$畻鍏紡
+balance_change_id 浣欓鍙樺姩璁板綍ID锛屼富閿?member_balance_changes.id
+member_id 浼氬憳ID member_balance_changes.member_id
+site_id 闂ㄥ簵ID member_balance_changes.site_id
+change_amount 鍙樺姩閲戦锛堟=澧炲姞锛岃礋=鍑忓皯锛?member_balance_changes.change_amount
+balance_before 鍙樺姩鍓嶄綑棰?member_balance_changes.balance_before
+balance_after 鍙樺姩鍚庝綑棰?member_balance_changes.balance_after
+change_type_code 鍙樺姩绫诲瀷缂栫爜锛堝厖鍊?娑堣垂/璋冩暣鈥︼級 member_balance_changes.change_type锛孌WD 鍏宠仈 dim_balance_change_type
+relate_id 鍏宠仈涓氬姟璁板綍ID member_balance_changes.relate_id
+pay_method_code 娑夊強鏀粯鏂瑰紡锛堜粎瀵瑰厖鍊肩被鏈夋剰涔夛級 member_balance_changes.pay_method 鎴栫敱 ods_recharge_record.pay_method 鍥炲~
+change_time 鍙樺姩鏃堕棿 member_balance_changes.change_time
+operator_id 鎿嶄綔鍛業D member_balance_changes.operator_id
+remark 澶囨敞 member_balance_changes.remark
+
+鈥?change_id (BIGINT) - 浣欓鍙樺姩ID锛堜富閿級銆?
+鈥?member_id (BIGINT) - 浼氬憳ID锛屽叧鑱擠IM_MEMBER銆?
+鈥?change_type_code (INT) - 鍙樺姩绫诲瀷缂栫爜锛屽叧鑱擠IM_BALANCE_CHANGE_TYPE缁磋〃銆?
+鈥?change_type_name (STRING) - 鍙樺姩绫诲瀷鍚嶇О锛堝鈥滃厖鍊煎埌璐︹€濄€佲€滄秷璐规墸娆锯€濄€佲€滃悗鍙拌皟鏁粹€濓級銆?
+鈥?related_id (BIGINT) - 鍏宠仈涓氬姟ID锛堝厖鍊艰褰旾D鎴栬鍗曠粨绠桰D绛夛級銆?
+鈥?change_amount (DECIMAL(10,2)) - 鍙樺姩閲戦锛?澧炲姞/-鍑忓皯锛夈€?
+鈥?balance_after (DECIMAL(10,2)) - 鍙樺姩鍚庝綑棰濄€?
+鈥?change_time (DATETIME) - 鍙樺姩鏃堕棿銆?
+鈥?pay_method_code (INT) - 鏀粯鏂瑰紡缂栫爜锛堜粎褰揷hange_type涓哄厖鍊兼椂鏈夋剰涔夛級銆?
+鈥?pay_method_name (STRING) - 鏀粯鏂瑰紡鍚嶇О銆?
+鈥?operator_id (BIGINT) - 鎿嶄綔鍛業D銆?
+鏉ユ簮鍙婇€昏緫锛?鐢監DS_BALANCE_CHANGE娓呮礂銆傜敱浜庝綑棰濆彉鍔ㄦ湰韬笉鏄牳蹇冨垎鏋愭寚鏍囷紙澶ч儴鍒嗗彲浠ヤ粠鍏呭€煎拰娑堣垂鎺ㄥ锛夛紝姝act鍙€夈€傚鏋滀繚鐣欙細change_type_code缁熶竴缂栫爜锛岄渶寤虹珛DIM_BALANCE_CHANGE_TYPE锛屽1=鍏呭€笺€?=娑堣垂銆?=璋冩暣绛夈€傚彉鍔ㄧ被鍨嬪悕绉伴€氳繃缁磋〃缁欏嚭鎴栫洿鎺ュ啓鏄庛€俽elated_id鐢ㄤ簬鐏垫椿鍏宠仈瀵瑰簲浜嬪疄锛屽鍏呭€煎搴擣ACT_RECHARGE.id锛屾秷璐瑰搴擣ACT_PAYMENT/FACT_ORDER_SUMMARY.id锛堝彲鑳芥瘮杈冨鏉傛槧灏勶紝鍙湪ETL涓儴鍒嗗疄鐜帮紝瀵瑰簲涓嶄笂鍒欑暀瀛業D澶囩敤锛夈€傛敮浠樻柟寮忎粎瀵瑰厖鍊煎瀷鐨勬湁鎰忎箟锛岀洿鎺ヤ粠ODS鍙栥€侳ACT_BALANCE_CHANGE鏈夊姪浜庢牳瀵逛細鍛樿祫閲戞祦锛屼絾鍏舵暟鎹熀鏈彲浠ョ敱鍏朵粬浜嬪疄鎺ㄧ畻锛屽洜姝ゅ湪鏁版嵁閲忎笉澶ф椂淇濈暀浠ュ妫€鏌ャ€?
+________________________________________
+浠ヤ笂浜嬪疄琛ㄦ兜鐩栦細鍛樻秷璐圭殑涓昏鏄庣粏銆傛墍鏈変簨瀹炶〃鍧囧寘鍚玸ite_id浠ユ敮鎸佸搴楀垎寮€缁熻锛屼互鍙婂寘鍚浉搴旂殑缁村害ID鏉ヨ繛鎺ョ淮搴﹁〃锛屼粠鑰岃幏寰椾赴瀵岀淮搴﹀睘鎬с€?
+鍦ㄤ簨瀹炴暟鎹竻娲楄繃绋嬩腑锛岄渶瑕佺‘淇濓細
+- 鎵€鏈夊叧鑱旈敭鏈夋晥锛堝閿€鍞褰曢噷鍟嗗搧ID銆佽鍗曞彿鑳芥壘鍒板搴旂淮琛ㄦ垨浜嬪疄锛夈€?
+- 閲戦瀛楁鍗曚綅缁熶竴涓哄厓锛岀被鍨嬬粺涓€浣跨敤DECIMAL(10,2)銆?
+- 鏃堕棿瀛楁鏍囧噯鍖栦负Timestamp鎴朌ATETIME锛屼笖瀵瑰簲鏈湴鏃跺尯锛堟棩鍒囨寜鑷劧鏃?0:00锛夈€?
+4. DWS灞傝〃瀹氫箟锛堟眹鎬诲眰锛?
+DWS 灞備富瑕侀潰鍚戝垎鏋愰渶姹傦紝瀵规槑缁嗕簨瀹烇紙DWD锛夎繘琛屾眹鎬诲拰閲嶆瀯锛屽舰鎴愪究浜庣洿鎺ュ彇鐢ㄧ殑璁㈠崟绾у琛ㄥ拰涓婚姹囨€昏〃銆傛湰鏂规閲嶇偣璁捐璁㈠崟缁撶畻姹囨€诲琛?DWS_ORDER_SUMMARY锛屼互銆屾瘡绗旂粨璐﹁褰曚竴琛屻€嶄负绮掑害锛屾暣鍚堜竴寮犺鍗?缁撶畻鍗曠殑涓昏鎸囨爣锛岀敤浜庝粠璁㈠崟瑙嗚鍒嗘瀽锛?
+鈥?瀹㈠崟浠蜂笌娑堣垂缁撴瀯锛堝彴璐?鍟嗗搧/鍔╂暀/鍥㈣喘锛?
+鈥?浼樻儬鏋勬垚锛堜細鍛樻姌鎵c€佹墜宸ユ姌鎵c€佸洟璐埜锛?
+鈥?鏀粯涓庤祫閲戝彛寰勶紙鍚偍鍊?/ 闈炲偍鍊笺€侀€€娆俱€佹湁鏁堟祦姘达級
+鈥?浼氬憳璐$尞涓庤涓猴紙浼氬憳鏍囪瘑銆佷細鍛樺揩鐓х瓑锛?
+濡傞渶鏃ユ姤绛夊叾浠栨眹鎬伙紝鍙湪鏈〃鍩虹涓婃寜鏃ユ湡銆侀棬搴楃瓑缁村害杩涜浜屾姹囨€伙紙鏈涓嶅睍寮€锛夈€?
+________________________________________
+4.1 DWS_ORDER_SUMMARY锛堣鍗曠粨绠楁眹鎬昏〃锛夋杩?
+鈥?琛ㄥ悕锛欴WS_ORDER_SUMMARY锛堣鍗曠粨绠楁眹鎬昏〃锛?
+鈥?绮掑害锛氫竴绗旇鍗曠粨绠?/ 缁撹处鍗曪紙order_settle_id锛?
+鈥?涓婚敭锛歰rder_settle_id锛堣鍗曠粨绠?ID锛?
+鈥?鑱氬悎閿細site_id + order_settle_id锛堥棬搴楃淮搴︿笅鍞竴锛?
+鈥?涓昏鐢ㄩ€旓細
+o 璁㈠崟绾х粡钀ュ垎鏋愶細瀹㈠崟浠枫€佹秷璐圭粨鏋勩€佹姌鎵g粨鏋勩€佹敮浠樼粨鏋勩€佷細鍛樿础鐚?
+o 璧勯噾瑙嗚鍒嗘瀽锛氭湁鏁堟祦姘达紙鍚厖鍊硷級銆佸噣鏀跺叆
+o 閰嶅悎 DWD 浜嬪疄鍜岀淮琛紝鏀拺澶氱淮 OLAP 涓庢姤琛?
+鏃堕棿涓庨噾棰濆彛寰勭害瀹?
+鈥?璁㈠崟鏃ユ湡锛歰rder_date = DATE(settle_time)锛屾寜鑷劧鏃ュ垝鍒嗭紝涓嶅啀鍋?4 鐐瑰垏鏃ャ€?
+鈥?鏀粯缁熻锛氭墍鏈夆€滄敮浠橀噾棰濃€濈粺璁″熀浜?FACT_PAYMENT锛屼粎鍖呭惈鏀粯鏄庣粏锛屼笉鍚€€娆撅紱
+閫€娆惧崟鐙€氳繃 refund_amount 瀛楁鍜岄€€娆句簨瀹炶〃浣撶幇銆?
+鈥?閲戦瀛楁锛氶櫎鐗瑰埆璇存槑澶栵紝鍧囦负鈥滆鍗曠骇姹囨€诲€尖€濓紝鍗冲悓涓€璁㈠崟涓嬬浉鍏虫槑缁嗛噾棰濈殑姹囨€荤粨鏋溿€?
+鈥?浼樻儬鎷嗗垎锛氬彴璐广€佸晢鍝併€佸姪鏁欐槑缁嗕腑娑夊強浼氬憳鎶樻墸銆佹墜宸ユ姌鎵c€佸洟璐埜鎶垫墸绛夛紝鍧囧湪璁㈠崟绾ц繘琛屽綊骞躲€?
+鏉ユ簮浼樺厛绾х害瀹?
+鈥?鑻ユ煇璁㈠崟绾ф寚鏍囧彲鍚屾椂浠庡皬绁?ODS 琛ㄤ笌 DWD fact 姹囨€诲緱鍒帮細
+o 鎺ㄨ崘浠?DWD fact 涓轰富锛堝缓妯$粺涓€鍙e緞锛夛紱
+o ODS 灏忕エ閲戦鐢ㄤ簬瀵硅处涓庢牎楠岋紱
+o 瀵硅处涓嶄竴鑷存椂锛屼互瀹為檯涓氬姟绾﹀畾涓哄噯骞跺湪 ETL 瑙勫垯涓浐鍖栥€?
+________________________________________
+4.2 瀛楁璁捐
+浠ヤ笅鎸夊姛鑳藉垎缁勫垪鍑哄瓧娈点€傚瓧娈电被鍨嬪彲鏍规嵁鐩爣鏁颁粨瀹炵幇寰皟锛岄粯璁ら噾棰濈被涓?DECIMAL(18,2)锛屾暟閲忕被涓?INT 鎴?DECIMAL(18,2)锛屾爣蹇楃被涓?TINYINT銆?
+4.2.1 鍩虹缁村害涓庝富閿俊鎭?
+鈥?order_settle_id (BIGINT)
+璁㈠崟缁撶畻 ID锛屼富閿€備竴绗旇鍗曠粨绠楃殑鍞竴鏍囪瘑銆?
+鈥?order_trade_no (BIGINT)
+璁㈠崟浜ゆ槗鍙枫€備笌 order_settle_id 涓€涓€瀵瑰簲锛堝綋鍓嶅亣瀹氫竴鍗曚竴缁擄紝濡傚悗缁瓨鍦ㄥ娆$粨绠楅渶鍐嶆槑纭鍒欙級銆?
+鈥?order_type (STRING)
+璁㈠崟绫诲瀷鏍囪瘑銆?娑堣垂鍗? = 瀛樺湪鍙拌垂鐨勬秷璐?锛?鍔╂暀鍗? =浠呭姪鏁欐湇鍔★紱鈥欏厖鍊煎崟鈥?浠呭厖鍊兼棤娑堣垂銆傜敤浜庡湪 ETL 涓喅瀹氭湁鏁堟祦姘寸殑鍒嗘憡鏂瑰紡銆?
+鈥?site_id (BIGINT)
+闂ㄥ簵 ID锛屽叧鑱?DIM_SITE 鑾峰彇闂ㄥ簵鍚嶇О銆佸尯鍩熺瓑淇℃伅銆?
+鈥?order_date (DATE)
+璁㈠崟鏃ユ湡锛堣嚜鐒舵棩锛夈€備粠 settle_time 鎻愬彇鏃ユ湡閮ㄥ垎锛岀敤浜庢寜鏃ユ眹鎬汇€?
+鈥?settle_time (DATETIME)
+缁撹处瀹屾垚鏃堕棿锛屽嵆璁㈠崟瀹為檯鍏抽棴鏃堕棿銆?
+鈥?member_id (BIGINT, 鍙┖)
+璁㈠崟缁戝畾鐨勪細鍛?ID锛屾棤浼氬憳鍒欎负绌恒€?
+鈥?member_flag (TINYINT)
+浼氬憳鏍囪瘑锛? 琛ㄧず浼氬憳鍗曪紙member_id 闈炵┖锛夛紝0 琛ㄧず闈炰細鍛樺崟锛屼究浜庣瓫閫夌粺璁°€?
+4.2.2 璁㈠崟绾ч噾棰濆瓧娈碉紙娑堣垂涓庝紭鎯犳媶鍒嗭級
+鈥?total_table_fee (DECIMAL(18,2))
+鍙拌垂瀹炴敹鎬婚銆傝璁㈠崟鎵€鏈夊彴璐瑰疄闄呮敹鍙栭噾棰濅箣鍜岋紙宸叉墸闄ゆ姌鎵d笌鍒告姷鎵o級銆?
+鈥?total_product_amount (DECIMAL(18,2))
+鍟嗗搧瀹炴敹鎬婚銆傝鍗曚腑鎵€鏈夊晢鍝佸疄鏀堕噾棰濅箣鍜岋紙涓嶅惈閫€娆?浣滃簾琛岋級銆?
+鈥?total_assistant_fee (DECIMAL(18,2))
+鍔╂暀鏈嶅姟瀹炴敹鎬婚銆傝鍗曚腑鎵€鏈夋湭浣滃簾鍔╂暀鏈嶅姟瀹為檯鏀惰垂鎬婚銆?
+鈥?total_coupon_deduction (DECIMAL(18,2))
+鍥㈣喘鍒告姷鎵f€婚銆傛寜鍒糕€滄姷鎵i噾棰濃€濓紙璁拌处渚х殑鐢ㄥ埜鎶垫墸锛夋眹鎬汇€?
+鈥?manual_discount_amount (DECIMAL(18,2))
+鎵嬪伐浼樻儬鎬婚銆傚寘鍚彴璐广€佸姪鏁欙紙浠ュ強濡傛湁鍙瘑鍒殑鍟嗗搧鎵嬪伐鎶樻墸锛夌殑浜哄伐鍑忓厤閲戦銆?
+鈥?member_discount_amount (DECIMAL(18,2))
+浼氬憳鎶樻墸鎬婚銆傚洜浼氬憳韬唤浜彈鐨勪紭鎯犳€诲拰锛堝彲鍚彴璐广€佸姪鏁欍€佸晢鍝佺殑浼氬憳鎶樻墸锛夈€?
+鈥?order_original_amount (DECIMAL(18,2))
+璁㈠崟鍘熶环鎬婚锛堟湭鎵e噺浠讳綍浼樻儬/鍒哥殑搴斾粯閲戦锛夛紝瀹氫箟涓猴細
+order_original_amount = total_table_fee + total_product_amount + total_assistant_fee + member_discount_amount + manual_discount_amount + total_coupon_deduction銆?
+鈥?order_final_amount (DECIMAL(18,2))
+璁㈠崟搴旀敹閲戦銆傛墸闄ゆ墍鏈変紭鎯犱笌鍒告姷鎵e悗鐨勫疄鏀堕噾棰濓紝鐞嗚涓婂簲婊¤冻锛?
+order_final_amount = total_table_fee + total_product_amount + total_assistant_fee锛?
+骞朵笌灏忕エ ODS 涓殑璁㈠崟搴旀敹閲戦瀛楁淇濇寔瀵归綈锛屽瀛樺湪宸紓锛屼互灏忕エ瀹為檯鍙e緞涓哄噯骞跺湪 ETL 灞傝繘琛岃皟鏁淬€?
+4.2.3 鏀粯鎷嗗垎涓庨€€娆俱€佸噣鏀跺叆瀛楁
+鈥?total_paid_amount (DECIMAL(18,2))
+瀹炰粯閲戦鎬昏銆傞【瀹㈠疄闄呮敮浠樼殑鎬婚噾棰濓紙鍖呮嫭鐜伴噾/鐢靛瓙鏀粯 + 鍌ㄥ€煎崱鏀粯锛夈€?
+鈥?stored_card_deduct (DECIMAL(18,2))
+鍌ㄥ€煎崱鏀粯閲戦銆傝璁㈠崟鐢变細鍛樺偍鍊间綑棰濇敮浠樼殑閲戦銆?
+鈥?external_paid_amount (DECIMAL(18,2))
+澶栭儴鏀粯閲戦锛堥潪鍌ㄥ€肩被鏀粯锛?= total_paid_amount - stored_card_deduct銆?
+鈥?pay_cash (DECIMAL(18,2), 鍙€?
+鐜伴噾鏀粯閲戦銆?
+鈥?pay_wechat (DECIMAL(18,2), 鍙€?
+寰俊鏀粯閲戦銆?
+鈥?pay_alipay (DECIMAL(18,2), 鍙€?
+鏀粯瀹濇敮浠橀噾棰濄€?
+鈥?pay_other (DECIMAL(18,2), 鍙€?
+鍏朵粬鏀粯娓犻亾閲戦锛堝閾惰仈鍗°€佸叾浠栫涓夋柟鏀粯绛夛級锛屽彲浣滀负闄ょ幇閲?寰俊/鏀粯瀹?鍌ㄥ€煎崱涔嬪鐨勬眹鎬汇€?
+璇存槑锛氬嚭浜庘€滈伩鍏嶅啓姝绘敮浠樻柟寮忔灇涓锯€濈殑鍘熷垯锛屽叿浣撴敮浠樻笭閬撳垪锛坧ay_xxx锛夊彲鎸夊疄闄呴渶瑕侀€夋嫨鏄惁鍦ㄥ琛ㄥ浐鍖栵紝濡傛敮浠樻柟寮忓彉鍖栭绻侊紝鍙粎淇濈暀鍏抽敭鍖哄垎锛堝鍌ㄥ€?闈炲偍鍊硷級锛屽叾浣欏湪鎶ヨ〃灞傞€氳繃鍏宠仈鏀粯缁磋〃閫忚銆?
+鈥?pay_method_count (INT)
+鏈崟浣跨敤鐨勬敮浠樻柟寮忕绫绘暟锛圖ISTINCT 鏀粯鏂瑰紡缂栫爜锛夈€?
+鈥?refund_amount (DECIMAL(18,2))
+閫€娆鹃噾棰濄€傛湰璁㈠崟鐩稿叧閫€娆炬€婚锛堟寜姝f暟瀛樺偍锛夛紝鍖呭惈鍏ㄩ鎴栭儴鍒嗛€€娆俱€?
+鈥?net_income (DECIMAL(18,2))
+鍑€鏀舵閲戦銆傛爣鍑嗗彛寰勪负锛?
+net_income = total_paid_amount - refund_amount銆?
+琛ㄧず璇ヨ鍗曞湪鏀舵瑙嗚涓婄殑鍑€鍏ヨ处閲戦銆?
+4.2.4 鏁伴噺绫讳笌杈呭姪鍒嗘瀽瀛楁
+鈥?item_count (INT)
+鍟嗗搧琛屾暟銆傝鍗曚腑涓嶅悓鍟嗗搧琛岀殑鏁伴噺锛堝幓閲嶅悗鐨勮鏁帮級銆?
+鈥?total_item_quantity (DECIMAL(18,2))
+鍟嗗搧鎬绘暟閲忋€傛寜浠舵暟/閲嶉噺绛夊崟浣嶆眹鎬荤殑鎬绘暟銆?
+鈥?assistant_count (INT)
+鍔╂暀鏈嶅姟鎬绘鏁般€傝鍗曚腑鍙戠敓鐨勬湭浣滃簾鍔╂暀鏈嶅姟璁板綍鏁般€?
+鈥?table_count (INT)
+浣跨敤鐨勫彴妗屾暟閲忋€傝鍗曟秹鍙婄殑涓嶅悓鍙版鏁帮紙鎹㈠彴鍦烘櫙鍙兘澶т簬 1锛夈€?
+鈥?duration_total (INT)
+鍙版浣跨敤鎬绘椂闀匡紙鍒嗛挓锛夈€傚鏈夊鍙版锛屼細杩涜绱姞銆?
+鈥?avg_item_price (DECIMAL(18,2))
+鍟嗗搧骞冲潎鍗曚环锛堝疄鏀?/ 鏁伴噺锛夛紝瀹氫箟涓猴細
+CASE WHEN total_item_quantity > 0 THEN total_product_amount / total_item_quantity ELSE NULL END銆?
+4.2.5 璁㈠崟绾у揩鐓х淮搴﹀瓧娈?
+鈥?member_name_snapshot (STRING)
+缁撹处鏃朵細鍛樺鍚嶅揩鐓с€傛潵鑷皬绁?ODS锛涚敤浜庡弽鏄犲綋鏃朵細鍛樹俊鎭紙浼氬憳璧勬枡鍚庣画鍙兘鍙樻洿锛夈€?
+鈥?member_mobile_snapshot (STRING)
+缁撹处鏃朵細鍛樻墜鏈哄彿蹇収銆?
+鈥?cashier_name (STRING)
+鏀堕摱鍛樺鍚嶃€傚鐞嗘璁㈠崟缁撹处鐨勬搷浣滃憳锛屽彲鐢?ODS 鏀堕摱鍛樺瓧娈垫竻娲楀緱鍒般€?
+鈥?remark (STRING)
+璁㈠崟澶囨敞銆傚灏忕エ鎴栬鍗曚腑鐨勯檮鍔犺鏄庛€?
+4.2.6 璁拌处娴佹按瀛楁锛圔ook Flow锛?
+鐢ㄤ簬浠庘€滅粡钀ョ粨鏋?/ 璁拌处绉戠洰鈥濊瑙掞紝鍒嗘瀽鍙拌垂銆佸姪鏁欍€佸晢鍝併€佸洟璐湪钀ヤ笟棰濅腑鐨勬瀯鎴愶紝涓嶅叧娉ㄦ敮浠樻柟寮忋€?
+鈥?book_table_flow (DECIMAL(18,2))
+鍙拌垂璁拌处娴佹按銆傝璁㈠崟鍦ㄢ€滃彴璐光€濈鐩笅鐨勮惀涓氭敹鍏ワ紙鍚偍鍊兼敮浠橈紝涓嶅惈浣滃簾/鍙栨秷锛夈€?
+鈥?book_assistant_flow (DECIMAL(18,2))
+鍔╂暀璁拌处娴佹按銆傝璁㈠崟鍦ㄢ€滃姪鏁欐湇鍔♀€濈鐩笅鐨勮惀涓氭敹鍏ワ紙浠呯粺璁℃湭浣滃簾涓斿疄闄呰璐圭殑鍔╂暀鏈嶅姟锛夈€?
+鈥?book_goods_flow (DECIMAL(18,2))
+鍟嗗搧璁拌处娴佹按銆傝璁㈠崟鍦ㄢ€滃晢鍝侀攢鍞€濈鐩笅鐨勮惀涓氭敹鍏ワ紙涓嶅惈璧犲搧锛夈€?
+鈥?book_group_flow (DECIMAL(18,2))
+鍥㈣喘璁拌处娴佹按銆傝璁㈠崟浣跨敤鍥㈣喘鍒稿舰鎴愮殑鏀跺叆锛屾寜鍥㈣喘鈥滃钩鍙扮粨绠椾环鈥濆叆璐︺€?
+鈥?book_order_flow (DECIMAL(18,2))
+璁㈠崟璁拌处鎬绘祦姘达紝鐢ㄤ簬缁忚惀缁撴瀯鍒嗘瀽銆傚畾涔変负锛?
+book_order_flow = book_table_flow + book_assistant_flow + book_goods_flow + book_group_flow銆?
+4.2.7 璁㈠崟鏈夋晥娴佹按瀛楁锛圗ffective Order Flow锛?
+浠庘€滆祫閲戣瑙?+ 鍚厖鍊尖€濈殑璐㈠姟鍙e緞瀹氫箟璁㈠崟瀵归棬搴楀疄闄呰祫閲戞祦鍏ョ殑璐$尞銆?
+鈥?order_effective_consume_cash (DECIMAL(18,2))
+闈炲偍鍊肩被鏀粯涓紝鐢ㄤ簬娑堣垂锛堝彴璐?+ 鍔╂暀 + 鍟嗗搧 + 鍥㈣喘锛夌殑閲戦銆?
+鈥?order_effective_recharge_cash (DECIMAL(18,2))
+闈炲偍鍊肩被鏀粯涓紝鐢ㄤ簬鍏呭€肩殑閲戦锛堢函鍏呭€煎崟锛夈€?
+鈥?order_effective_flow (DECIMAL(18,2))
+璁㈠崟鏈夋晥娴佹按銆傚畾涔変负锛?
+order_effective_flow = order_effective_consume_cash + order_effective_recharge_cash + book_group_flow銆?
+璇存槑锛?
+鈥?鎸夌害瀹氾紝鈥滅幇閲戞敮浠樷€濈悊瑙d负鈥滈潪鍌ㄥ€肩被鏀粯鈥濓紙鐜伴噾 / 寰俊 / 鏀粯瀹?/ 閾惰鍗$瓑锛夛紱
+鍌ㄥ€煎崱鎵f浠呰涓哄唴閮ㄧ粨杞紝涓嶈涓烘柊澧炶祫閲戞祦鍏ャ€?
+鈥?鍥㈣喘浣跨敤鎸夆€滃钩鍙扮粨绠椾环鈥濊鍏ユ湁鏁堟祦姘达紙閫氳繃 book_group_flow 浣撶幇锛夛紝涓嶆寜鍒搁潰鍊笺€?
+________________________________________
+4.3 鏉ユ簮鍙婃眹鎬婚€昏緫璇存槑
+鏈〃涓昏閫氳繃璁㈠崟 ID / 浜ゆ槗鍙峰湪鍚?DWD 浜嬪疄琛ㄩ棿鍏宠仈锛屽苟鎸夎鍗曡仛鍚堝緱鍒般€備互涓嬩负鍏抽敭瀛楁鐨勬潵婧愪笌鍙e緞銆?
+4.3.1 娑堣垂涓庝紭鎯犵被閲戦瀛楁
+1. total_table_fee锛堝彴璐瑰疄鏀跺悎璁★級
+o 鏉ユ簮锛欶ACT_TABLE_USAGE.final_table_fee
+o 杩囨护锛歩s_canceled = 0锛堟湭浣滃簾鍙拌垂璁板綍锛?
+o 鑱氬悎锛氭寜 site_id, order_settle_id 鎴?order_trade_no 鍒嗙粍姹傚拰銆?
+o 濡?ODS 灏忕エ涓湁鍙拌垂姹囨€诲瓧娈碉紝鍙敤浜庡璐︺€?
+2. total_product_amount锛堝晢鍝佸疄鏀跺悎璁★級
+o 鏉ユ簮锛欶ACT_SALE_ITEM.final_amount
+o 寤鸿杩囨护锛歩s_refunded = 0 鎴栨寜瀹為檯涓氬姟鏍囪瘑鎺掗櫎宸查€€娆?浣滃簾琛屻€?
+o 鑱氬悎锛氭寜璁㈠崟缁村害姹傚拰銆?
+3. total_assistant_fee锛堝姪鏁欐湇鍔″疄鏀跺悎璁★級
+o 鏉ユ簮锛欶ACT_ASSISTANT_SERVICE.final_service_fee / final_fee
+o 杩囨护锛歩s_canceled = 0锛堟帓闄ゅ姪鏁欏簾闄よ褰曪級
+o 鑱氬悎锛氭寜璁㈠崟缁村害姹傚拰銆?
+鍔╂暀鐩稿叧閲戦鍙e緞璇存槑锛堟柊澧烇級
+DWS 灞傛墍鏈夆€滃姪鏁欑浉鍏抽噾棰濃€濆瓧娈碉紝缁熶竴閬靛惊浠ヤ笅鍙e緞锛?
+鈥?璁㈠崟缁村害鐨勫姪鏁欓噾棰濓紙濡傗€滃姪鏁欏熀纭€璇炬湰绗旇鍗曟€婚鈥濄€佲€滃姪鏁欓檮鍔犺鏈瑪璁㈠崟鎬婚鈥濓級鍧囩敱 DWD 鍔╂暀鏈嶅姟浜嬪疄琛ㄤ腑 final_fee 姹囨€昏€屾潵锛?
+o 鍩虹璇鹃噾棰濓細姹囨€?service_type = 鍩虹璇?涓?final_fee 鐨勯噾棰濓紱
+o 闄勫姞璇鹃噾棰濓細姹囨€?service_type = 闄勫姞璇?涓?final_fee 鐨勯噾棰濄€?
+鈥?is_canceled = 1 鐨勫簾闄よ褰曪細
+o 鍏?final_fee 鍙兘涓?0锛堝畬鍏ㄦ湭璁¤垂锛夋垨涓洪儴鍒嗚璐归噾棰濓紙宸叉湇鍔¢儴鍒嗚璐癸紝鏈湇鍔¢儴鍒嗕笉璁¤垂锛夛紱
+o DWS 璁㈠崟灞備粎鎸?final_fee 姹囨€伙紝鍥犳搴熼櫎鏈璐归儴鍒嗕笉浼氳鍏ヨ鍗曟湁鏁堟祦姘淬€?
+濡傞渶鍒嗘瀽鈥滃姪鏁欐湇鍔″師鏈簲鏀朵笌瀹為檯鍏ヨ处鈥濈殑宸锛屽彲鍦ㄤ笓棰樻姤琛ㄤ腑浣跨敤 DWD 鍔╂暀浜嬪疄琛ㄧ殑 base_fee 涓?final_fee 宸€硷紝骞剁粨鍚堝姪鏁欏簾闄よ〃涓殑鍘熷洜瀛楁杩涜鎷嗚В銆?
+
+4. total_coupon_deduction锛堝洟璐埜鎶垫墸閲戦锛?
+o 鏉ユ簮锛欶ACT_COUPON_USAGE.deduct_amount
+o 杩囨护锛氱姸鎬佷负姝e父鏍搁攢锛堝瀛樺湪 status 瀛楁闇€鎺掗櫎寮傚父鐘舵€侊級
+o 鑱氬悎锛氭寜璁㈠崟缁村害姹傚拰銆?
+5. member_discount_amount 涓?manual_discount_amount
+o 鍙拌垂銆佸姪鏁欏眰闈㈤€氬父瀛樺湪鏄庣‘鐨勪細鍛樻姌鎵e瓧娈靛拰鎵嬪伐鎶樻墸瀛楁锛?
+o 鍟嗗搧灞傞潰鑻ユ棤娉曞尯鍒嗘姌鎵g被鍨嬶紝鍙噰鐢ㄤ繚瀹堣鍒欙細
+飩?灏嗗晢鍝?discount_amount 缁熶竴璁″叆 member_discount_amount锛堟垨鐢变笟鍔″彛寰勭粺涓€褰掔被锛夛紱
+飩?manual_discount_amount 鑷冲皯鍖呮嫭鍙拌垂涓庡姪鏁欑殑鎵嬪伐鎶樻墸锛?
+o 鑻ユ湭鏉ュ晢鍝佹姌鎵e彲鎷嗗垎涓衡€滀細鍛樻姌鎵?vs 鎵嬪伐鎶樻墸鈥濓紝瀵瑰簲瀛楁鍙啀璋冩暣鎷嗗垎閫昏緫銆?
+6. order_original_amount銆乷rder_final_amount
+o 鎸夊叕寮忚绠楋紝纭繚涓庢槑缁嗗拰灏忕エ閲戦涓€鑷达紱
+o 浼樺厛浠?DWD 姹囨€讳负涓伙紝灏忕エ ODS 鐢ㄤ簬瀵硅处鍜屽紓甯告鏌ャ€?
+4.3.2 璁拌处娴佹按鍙e緞锛圔ook Flow锛?
+璁拌处娴佹按鍙叧娉ㄢ€滄秷璐圭粨鏋勭鐩€濓紝涓嶅叧蹇冩敮浠樻柟寮忎笌璧勯噾鏉ユ簮锛屼笉鍖呭惈鍏呭€硷紝涔熶笉鐩存帴鍥炴粴閫€娆俱€?
+1. book_table_flow锛堝彴璐硅璐︽祦姘达級
+o 鏉ユ簮琛細FACT_TABLE_USAGE
+o 杩囨护锛歰rder_trade_no = 褰撳墠璁㈠崟锛宨s_canceled = 0
+o 鑱氬悎锛歜ook_table_flow = SUM(final_table_fee)
+o 鍚箟锛氬凡缁忔墸闄ゆ墍鏈変紭鎯犲拰鍒告姷鎵e悗璁板叆鈥滃彴璐光€濈鐩殑钀ヤ笟鏀跺叆銆?
+2. book_assistant_flow锛堝姪鏁欒璐︽祦姘达級
+o 鏉ユ簮琛細FACT_ASSISTANT_SERVICE
+o 杩囨护锛歰rder_trade_no = 褰撳墠璁㈠崟锛宨s_canceled = 0
+o 鑱氬悎锛歜ook_assistant_flow = SUM(final_fee)
+o 鍚箟锛氫粎缁熻瀹為檯瀹屾垚骞惰璐圭殑鍔╂暀鏈嶅姟銆?
+3. book_goods_flow锛堝晢鍝佽璐︽祦姘达級
+o 鏉ユ簮琛細FACT_SALE_ITEM
+o 杩囨护锛歰rder_trade_no = 褰撳墠璁㈠崟锛宨s_gift = 0锛堟帓闄よ禒鍝侊級
+o 鑱氬悎锛歜ook_goods_flow = SUM(final_amount)
+o 鍚箟锛氫笉璁″叆璧犻€佸晢鍝佺殑閲戦锛岃禒鍝佷笉鏋勬垚钀ヤ笟鏀跺叆銆?
+4. book_group_flow锛堝洟璐璐︽祦姘达級
+o 鏉ユ簮琛細FACT_COUPON_USAGE
+o 杩囨护锛歰rder_trade_no = 褰撳墠璁㈠崟锛岀姸鎬佷负姝e父鏍搁攢
+o 鑱氬悎锛歜ook_group_flow = SUM(settle_price)
+o 鍚箟锛氭寜鍥㈣喘鈥滃钩鍙扮粨绠椾环鈥濆叆璐︼紝鑰岄潪鍒搁潰鍊笺€傚寮犲埜绱姞銆?
+5. book_order_flow锛堣鍗曡璐︽€绘祦姘达級
+o 瀹氫箟锛?
+book_order_flow = book_table_flow + book_assistant_flow + book_goods_flow + book_group_flow
+o 鐢ㄩ€旓細
+飩?鍥炵瓟鈥滆繖绗旇鍗曞湪鍙拌垂 / 鍔╂暀 / 鍟嗗搧 / 鍥㈣喘鍚勮鍏ヤ簡澶氬皯钀ヤ笟鏀跺叆鈥濓紱
+飩?涓哄悇绉戠洰钀ヤ笟缁撴瀯鍗犳瘮鍒嗘瀽鎻愪緵鍩虹銆?
+o 閫€娆撅細璁拌处娴佹按涓嶇洿鎺ュ啿鍑忛€€娆撅紱閫€娆惧湪 FACT_REFUND 鍜?refund_amount 涓崟鐙綋鐜般€傚闇€鈥滆璐﹀噣娴佹按鈥濆彛寰勶紝鍙湪鎶ヨ〃灞傦細
+璁拌处鍑€娴佹按 = SUM(book_order_flow) - 瀵瑰簲閫€娆炬姌杩旈噾棰濄€?
+4.3.3 璁㈠崟鏈夋晥娴佹按鍙e緞锛圗ffective Order Flow锛?
+璁㈠崟鏈夋晥娴佹按浠庤祫閲戝疄闄呮祦鍏ヨ瑙掑畾涔夛紝鍏虫敞鈥滄柊澧炲閮ㄨ祫閲?+ 鍥㈣喘缁撶畻鏀跺叆鈥濄€?
+鍩烘湰鍘熷垯
+鈥?鍌ㄥ€煎崱鏀粯锛氳涓哄唴閮ㄨ祫閲戝湪鍌ㄥ€艰处鎴蜂笌娑堣垂涔嬮棿杞Щ锛屼笉璁″叆鈥滄柊澧炶祫閲戞祦鍏モ€濓紝浣嗗叾瀵瑰簲鐨勬秷璐逛粛璁″叆鍚?book_* 娴佹按銆?
+鈥?闈炲偍鍊肩被鏀粯锛堢幇閲戙€佸井淇°€佹敮浠樺疂銆侀摱琛屽崱绛夛級锛氳涓洪棬搴楃湡瀹炴祦鍏ヨ祫閲戙€?
+鈥?鍏呭€硷細
+o 鍏呭€煎彂鐢熸椂锛堥潪鍌ㄥ€兼敮浠樺厖鍊煎埌鍌ㄥ€艰处鎴凤級璁″叆鏈夋晥娴佹按锛?
+o 涔嬪悗浣跨敤鍌ㄥ€煎崱娑堣垂鏃朵笉鍐嶉噸澶嶈鍏ユ湁鏁堟祦姘淬€?
+鈥?鍥㈣喘锛氭寜骞冲彴缁撶畻浠疯鍏ユ湁鏁堟祦姘达紙閫氳繃 book_group_flow 鍙嶆槧锛夈€?
+1锛夐潪鍌ㄥ€兼秷璐规 order_effective_consume_cash
+鈥?鏉ユ簮锛欶ACT_PAYMENT + 褰撳墠璁㈠崟绫诲瀷鍒ゆ柇銆?
+鈥?鏀粯杩囨护锛?
+o 浠呯粺璁℃湰璁㈠崟涓敮浠樻柟寮忎负鈥滈潪鍌ㄥ€肩被鈥濈殑鏀粯璁板綍锛堝 pay_method_code 鈭堛€愮幇閲戙€佸井淇°€佹敮浠樺疂銆侀摱琛屽崱鈥︺€戯級锛屾帓闄ゅ偍鍊煎崱銆?
+鈥?涓氬姟鍓嶆彁锛?
+o 褰撳墠椤圭洰绾﹀畾鍗曠瑪璁㈠崟涓嶄細鍚屾椂鍖呭惈鈥滄秷璐?+ 鍏呭€尖€濓紝鍗宠鍗曡涔堟槸娑堣垂鍗曪紝瑕佷箞鏄厖鍊煎崟锛?
+o 鍦ㄦ鍓嶆彁涓嬪彲閲囩敤绠€鍗曞彛寰勶細
+飩?鑻ヨ鍗曚负娑堣垂鍗曪紙瀛樺湪鍙拌垂/鍟嗗搧/鍔╂暀绛夋秷璐癸紝涓旀棤鍏呭€艰锛夛細
+飩?order_effective_consume_cash = 璇ヨ鍗曟墍鏈夐潪鍌ㄥ€兼敮浠樻€婚
+飩?order_effective_recharge_cash = 0
+飩?濡傛湭鏉ュ嚭鐜板悓鍗曟棦娑堣垂鍙堝厖鍊肩殑澶嶆潅鍦烘櫙锛屽垯闇€鍦?ETL 涓寜鏄庣粏鎷嗗垎闈炲偍鍊奸噾棰濆苟鎸夋秷璐逛笌鍏呭€兼瘮渚嬪垎鎽娿€?
+2锛夐潪鍌ㄥ€煎厖鍊兼 order_effective_recharge_cash
+鈥?鏉ユ簮锛欶ACT_PAYMENT + 鍏呭€肩被浜嬪疄锛堝 FACT_RECHARGE 鎴?FACT_BALANCE_CHANGE 涓殑鍏呭€艰褰曪級銆?
+鈥?瀵逛簬鏍囪涓衡€滃厖鍊间笟鍔♀€濈殑璁㈠崟锛堟棤娑堣垂锛屼粎鍏呭€硷級锛?
+o order_effective_recharge_cash = 鏈鍗曟墍鏈夐潪鍌ㄥ€肩被鏀粯鎬婚
+o order_effective_consume_cash = 0
+鈥?鍚箟锛氳〃绀洪棬搴楅€氳繃鏈鍗曞悜浼氬憳璐︽埛鈥滃瓨鍏モ€濈殑鐪熷疄璧勯噾锛屽湪鍏呭€兼椂璁″叆鏈夋晥娴佹按锛屽悗缁秷璐瑰彧鍦ㄦ秷璐圭鍙嶆槧 book_* 娴佹按銆?
+3锛夎鍗曟湁鏁堟祦姘?order_effective_flow
+鈥?瀹氫箟锛?
+order_effective_flow = order_effective_consume_cash + order_effective_recharge_cash + book_group_flow
+鈥?瑙i噴锛?
+o order_effective_consume_cash锛氶潪鍌ㄥ€兼敮浠樼洿鎺ュ舰鎴愮殑娑堣垂鏀跺叆锛?
+o order_effective_recharge_cash锛氶潪鍌ㄥ€兼敮浠樺舰鎴愮殑鍏呭€兼敹鍏ワ紱
+o book_group_flow锛氬洟璐钩鍙颁互缁撶畻浠锋柟寮忎负闂ㄥ簵甯︽潵鐨勬敹鍏ワ紙鏈川涓婃槸骞冲彴浠f敹鍚庣粨绠楋級銆?
+鈥?鍚箟锛?
+o 浠庤储鍔¤搴︼紝鍙畝鍗曠悊瑙d负鈥滄湰璁㈠崟涓洪棬搴楀甫鏉ョ殑瀵瑰鐜伴噾鏀跺叆鈥濓紝鍖呭惈娑堣垂绫绘敹鍏ヤ笌鍏呭€肩被鏀跺叆锛屽苟灏嗗洟璐粨绠椾环绾冲叆瑙嗕负涓€绫诲閮ㄨ祫閲戞祦鍏ャ€?
+鈥?鑱氬悎浣跨敤锛?
+o 鏌愪竴鍛ㄦ湡锛堣嚜鐒舵棩 / 鑷劧鏈堢瓑锛夌殑鏈夋晥娴佹按锛?
+飩?SUM(order_effective_flow)
+o 鑻ラ渶鍑€鏈夋晥娴佹按鍙e緞锛屽彲鍦ㄦ姤琛ㄥ眰鎸夛細
+飩?鍑€鏈夋晥娴佹按 = SUM(order_effective_flow) - SUM(refund_amount)
+飩?鏄惁灏嗛€€娆惧啿鍑忔湁鏁堟祦姘村彇鍐充簬璐㈠姟瑕佹眰锛屽彲鍦ㄦ寚鏍囧畾涔変腑杩涗竴姝ュ浐鍖栥€?
+4) 鍏呭€煎崟璇嗗埆锛?
+鑻ユ煇 order_settle_id 鍦?FACT_TABLE_USAGE / FACT_SALE_ITEM / FACT_ASSISTANT_SERVICE 涓潎鏃犺褰曪紝
+浣嗗湪 FACT_RECHARGE 鎴?BALANCE_CHANGE锛坱ype=鍏呭€硷級涓瓨鍦ㄨ褰曪紝鍒欏皢璇ヨ鍗曟爣璁颁负 '鍏呭€艰鍗?锛?
+鍏跺搴旂殑闈炲偍鍊兼敮浠橀噾棰濆綊鍏?order_effective_recharge_cash銆?
+________________________________________
+4.4 鎸囨爣绀轰緥涓庡垎鏋愬彛寰?
+鍩轰簬 DWS_ORDER_SUMMARY锛屽彲鐩存帴鎴栬鐢熷嚭甯哥敤鍒嗘瀽鎸囨爣锛屽寘鎷絾涓嶉檺浜庯細
+鈥?瀹㈠崟浠凤細
+o 鍙敤 order_final_amount 鎴?total_paid_amount 鍋氫负瀹㈠崟娑堣垂棰濓紱
+o 鍛ㄦ湡瀹㈠崟浠?= 鍛ㄦ湡鍐呮秷璐规€婚 / 璁㈠崟鏁般€?
+鈥?浼氬憳璐$尞鐜囷細
+o 浼氬憳璁㈠崟鍗犳瘮锛歮ember_flag = 1 鐨勮鍗曟暟 / 鎬昏鍗曟暟锛?
+o 浼氬憳閲戦璐$尞锛歋UM(order_final_amount WHERE member_flag = 1) / SUM(order_final_amount)銆?
+鈥?鎶樻墸鐜囷細
+o 璁㈠崟鎶樻墸鐜囷細
+(member_discount_amount + manual_discount_amount + total_coupon_deduction) / order_original_amount銆?
+鈥?鍟嗗搧涓板瘜搴︿笌骞冲潎浠舵暟锛?
+o 姣忓崟鍟嗗搧鏁帮細AVG(total_item_quantity)锛?
+o 鍟嗗搧琛屾暟涓庡钩鍧囪鏁帮細AVG(item_count)銆?
+鈥?鏀粯缁撴瀯锛?
+o 闈炲偍鍊?vs 鍌ㄥ€硷細external_paid_amount 涓?stored_card_deduct 鐨勫崰姣旓紱
+o 鑻ヤ繚鐣?pay_xxx 瀛楁锛屽彲鐩存帴鍒嗘瀽鍚勬敮浠樻笭閬撶粨鏋勩€?
+鈥?缁忚惀缁撴瀯锛堣璐︽祦姘磋瑙掞級锛?
+o 鍙拌垂 / 鍟嗗搧 / 鍔╂暀 / 鍥㈣喘鍗犳瘮锛?
+鍚?book_*_flow / book_order_flow銆?
+鈥?鏈夋晥娴佹按涓庡噣鏀跺叆锛?
+o 鏈夋晥娴佹按锛歋UM(order_effective_flow)锛?
+o 鍑€鏀跺叆锛堣祫閲戝彛寰勶級锛歋UM(order_effective_flow) - SUM(refund_amount) 鎴栫洿鎺ヤ娇鐢?SUM(net_income)锛屼袱鑰呭彛寰勯渶鍦ㄦ姤琛ㄥ眰缁熶竴銆?
+________________________________________
+4.5 娉ㄦ剰浜嬮」
+鈥?鏃堕棿鍙e緞缁熶竴鎸夎嚜鐒舵棩锛坥rder_date锛夎繘琛屾棩绮掑害姹囨€伙紝鏆備笉鍖哄垎鏃舵锛堥棽鏃?蹇欐椂锛夌被鍒€?
+鈥?鏀粯鏂瑰紡銆佽鍗曠姸鎬佺瓑鏋氫妇鍊煎簲閫氳繃缁磋〃杞箟锛孌WS 灞傚彧淇濈暀蹇呰鐨勪唬鐮佷笌灏戦噺鍏抽敭鏍囩锛岄伩鍏嶅湪瀹借〃涓啓姝讳笟鍔℃灇涓俱€?
+鈥?澶氶棬搴楁墿灞曪細site_id 鏄富閿拰鍒嗙粍缁村害鐨勪竴閮ㄥ垎锛屽彲鐩存帴鎸夐棬搴椼€佸煄甯傘€佸尯鍩熺瓑缁村害杩涜姹囨€诲垎鏋愩€?
+鈥?閫€娆撅細
+o 涓嶇洿鎺ュ洖婊氳璐︽祦姘村瓧娈碉紙book_*锛夊拰鏈夋晥娴佹按瀛楁锛?
+o 閫氳繃 refund_amount 鍦ㄦ姤琛ㄥ眰瀹氫箟鈥滃噣鏀跺叆 / 鍑€鏈夋晥娴佹按鈥濈瓑鎸囨爣瀹炵幇鍐插噺銆?
+
+
diff --git a/tmp/README_FULL.md b/tmp/README_FULL.md
new file mode 100644
index 0000000..7d6c726
--- /dev/null
+++ b/tmp/README_FULL.md
@@ -0,0 +1,276 @@
+# 飞球 ETL 系统(ODS → DWD)— 详细版
+
+> 本文为项目的详细说明,保持与当前代码一致,覆盖 ODS 任务、DWD 装载、质检及开发扩展要点。
+
+---
+
+## 1. 项目概览
+
+面向门店业务的 ETL:从上游 API 或离线 JSON 采集订单、支付、会员、库存等数据,先落地 **ODS**,再清洗装载 **DWD**(含 SCD2 维度、事实增量),并输出质量校验报表。项目采用模块化/分层架构(配置、API、数据库、Loader/SCD、质量、调度、CLI、测试),统一通过 CLI 调度。
+
+---
+
+## 2. 快速开始(离线示例 JSON)
+
+**环境要求**:Python 3.10+;PostgreSQL;`.env` 关键项:
+- `PG_DSN=postgresql://local-Python:Neo-local-1991125@100.64.0.4:5432/LLZQ-test`
+- `INGEST_SOURCE_DIR=export/test-json-doc`
+
+**安装依赖**:
+```bash
+cd etl_billiards
+pip install -r requirements.txt
+```
+
+**一键 ODS → DWD → 质检(离线回放)**:
+```bash
+# 初始化 ODS + DWD
+python -m etl_billiards.cli.main --tasks INIT_ODS_SCHEMA,INIT_DWD_SCHEMA --pipeline-flow INGEST_ONLY
+
+# 灌入示例 JSON 到 ODS(可用 .env 的 INGEST_SOURCE_DIR 覆盖)
+python -m etl_billiards.cli.main --tasks MANUAL_INGEST --pipeline-flow INGEST_ONLY --ingest-source "export/test-json-doc"
+
+# 从 ODS 装载 DWD
+python -m etl_billiards.cli.main --tasks DWD_LOAD_FROM_ODS --pipeline-flow INGEST_ONLY
+
+# 质量校验报表
+python -m etl_billiards.cli.main --tasks DWD_QUALITY_CHECK --pipeline-flow INGEST_ONLY
+# 报表输出:etl_billiards/reports/dwd_quality_report.json
+```
+
+> 可按需单独运行:
+> - 仅建表:`python -m etl_billiards.cli.main --tasks INIT_ODS_SCHEMA`
+> - 仅 ODS 灌入:`python -m etl_billiards.cli.main --tasks MANUAL_INGEST`
+> - 仅 DWD 装载:`python -m etl_billiards.cli.main --tasks INIT_DWD_SCHEMA,DWD_LOAD_FROM_ODS`
+
+---
+
+## 3. 配置与路径
+- 示例数据目录:`export/test-json-doc`(可由 `.env` 的 `INGEST_SOURCE_DIR` 覆盖)。
+- 日志/导出目录:`LOG_ROOT`、`EXPORT_ROOT` 见 `.env`。
+- 报表:`etl_billiards/reports/dwd_quality_report.json`。
+- DDL:`etl_billiards/database/schema_ODS_doc.sql`、`etl_billiards/database/schema_dwd_doc.sql`。
+- 任务注册:`etl_billiards/orchestration/task_registry.py`(默认启用 INIT_ODS_SCHEMA、MANUAL_INGEST、INIT_DWD_SCHEMA、DWD_LOAD_FROM_ODS、DWD_QUALITY_CHECK)。
+
+**安全提示**:建议将数据库凭证保存在 `.env` 或受控秘钥管理中,生产环境使用最小权限账号。
+
+---
+
+
+
+
+## 正式环境(在线抓取 → 更新 ODS → 更新 DWD)
+核心入口 CLI:`python -m etl_billiards.cli.main`
+
+### 必备配置(建议通过环境变量或 `.env`)
+- 数据库:`PG_DSN`、`STORE_ID`
+- 在线抓取:`API_TOKEN`(可选 `API_BASE`、`API_TIMEOUT`、`API_PAGE_SIZE`、`API_RETRY_MAX`)
+- 输出目录(可选):`EXPORT_ROOT`、`LOG_ROOT`、`FETCH_ROOT`/`JSON_FETCH_ROOT`
+
+### 推荐定时方式 A(两段定时,更清晰)
+1) **更新 ODS(在线抓取 + 入库,FULL)**
+```bash
+python -m etl_billiards.cli.main \
+ --pipeline-flow FULL \
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID" \
+ --api-token "$API_TOKEN"
+```
+2) **ODS → DWD(将新增/变更同步到 DWD)**
+```bash
+python -m etl_billiards.cli.main \
+ --pipeline-flow INGEST_ONLY \
+ --tasks DWD_LOAD_FROM_ODS \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID"
+```
+
+### 推荐定时方式 B(一条命令串起来)
+同一条命令先跑在线抓取/入库任务,再跑 DWD 装载任务:
+```bash
+python -m etl_billiards.cli.main \
+ --pipeline-flow FULL \
+ --tasks PRODUCTS,TABLES,MEMBERS,ASSISTANTS,PACKAGES_DEF,ORDERS,PAYMENTS,REFUNDS,COUPON_USAGE,INVENTORY_CHANGE,TOPUPS,TABLE_DISCOUNT,ASSISTANT_ABOLISH,LEDGER,DWD_LOAD_FROM_ODS \
+ --pg-dsn "$PG_DSN" --store-id "$STORE_ID" \
+ --api-token "$API_TOKEN"
+```
+
+### pipeline-flow 说明
+- `FULL`:在线抓取落盘 + 本地清洗入库(ODS 任务会走抓取;`DWD_LOAD_FROM_ODS` 仅走入库阶段)
+- `FETCH_ONLY`:仅在线抓取落盘,不入库
+- `INGEST_ONLY`:仅从本地 JSON 回放入库(适合离线回放/补跑)
+
+## 4. 目录结构与关键文件
+- 根目录:`etl_billiards/` 主代码;`requirements.txt` 依赖;`run_etl.sh/.bat` 启动脚本;`.env/.env.example` 配置;`tmp/` 草稿/调试归档。
+- `config/`:`defaults.py` 默认值,`env_parser.py` 解析 .env,`settings.py` AppConfig 统一加载。
+- `api/`:`client.py` HTTP 请求、重试、分页。
+- `database/`:`connection.py` 连接封装;`operations.py` 批量 upsert;DDL SQL(ODS/DWD)。
+- `tasks/`:
+ - `init_schema_task.py`(INIT_ODS_SCHEMA/INIT_DWD_SCHEMA);
+ - `manual_ingest_task.py`(示例 JSON → ODS);
+ - `dwd_load_task.py`(ODS → DWD 映射、SCD2/事实增量);
+ - 其他任务按需扩展。
+- `loaders/`:ODS/DWD/SCD2 Loader 实现。
+- `scd/`:`scd2_handler.py` 处理维度 SCD2 历史。
+- `quality/`:质量检查器(行数/金额对照)。
+- `orchestration/`:`scheduler.py` 调度;`task_registry.py` 注册;`run_tracker.py` 运行记录;`cursor_manager.py` 水位管理。
+- `scripts/`:重建/测试/探活工具。
+- `docs/`:`ods_to_dwd_mapping.md` 映射说明;`ods_sample_json.md` 示例 JSON 说明;`dwd_quality_check.md` 质检说明。
+- `reports/`:质检输出(如 `dwd_quality_report.json`)。
+- `tests/`:单元/集成测试;`utils/`:通用工具;`backups/`:备份(若存在)。
+
+---
+
+## 5. 架构与流程
+执行链路(控制流):
+1) CLI(`cli/main.py`)解析参数 → 生成 AppConfig → 初始化日志/DB 连接;
+2) 调度层(`scheduler.py`)按 `task_registry.py` 中的注册表实例化任务,设置 run_uuid、cursor(水位)、上下文;
+3) 任务基类模板:
+ - 获取时间窗口/水位(cursor_manager);
+ - 拉取数据:在线模式调用 `api/client.py` 支持分页、重试;离线模式直接读取 JSON 文件;
+ - 解析与校验:类型转换、必填校验(如任务内部 parse/validate);
+ - 加载:调用 Loader(`loaders/`)执行批量 Upsert/SCD2/增量写入(底层用 `database/operations.py`);
+ - 质量检查(如需):质量模块对行数/金额等进行对比;
+ - 更新水位与运行记录(`run_tracker.py`),提交/回滚事务。
+
+数据流与依赖:
+- 配置:`config/defaults.py` + `.env` + CLI 参数叠加,形成 AppConfig。
+- API 访问:`api/client.py` 支撑分页/重试;离线 ingest 直接读文件。
+- DB 访问:`database/connection.py` 提供连接上下文;`operations.py` 负责批量 upsert/分页写入。
+- ODS:`manual_ingest_task.py` 读取 JSON → ODS 表(保留 payload/来源/时间戳)。
+- DWD:`dwd_load_task.py` 依据 `TABLE_MAP/FACT_MAPPINGS` 从 ODS 选取字段;维度走 SCD2(`scd/scd2_handler.py`),事实走增量;支持字段表达式(JSON->>、CAST)。
+- 质检:`quality` 模块或相关任务对 ODS/DWD 行数、金额等进行比对,输出 `reports/`。
+
+---
+
+## 6. ODS → DWD 策略
+1. ODS 留底:保留源主键、payload、时间/来源信息。
+2. DWD 清洗:维度 SCD2,事实按时间/水位增量;字段类型、单位、枚举标准化,保留可溯源字段。
+3. 业务键统一:site_id、member_id、table_id、order_settle_id、order_trade_no 等统一命名。
+4. 不过度汇总:DWD 只做明细/轻度清洗,汇总留待 DWS/报表。
+5. 去嵌套:数组展开为子表/子行,重复 profile 提炼为维度。
+6. 长期演进:优先加列/加表,避免频繁改已有表结构。
+
+---
+
+## 7. 常用 CLI
+```bash
+# 运行所有已注册任务
+python -m etl_billiards.cli.main
+# 运行指定任务
+python -m etl_billiards.cli.main --tasks INIT_ODS_SCHEMA,MANUAL_INGEST
+# 覆盖 DSN
+python -m etl_billiards.cli.main --pg-dsn "postgresql://user:pwd@host:5432/db"
+# 覆盖 API
+python -m etl_billiards.cli.main --api-base "https://api.example.com" --api-token "..."
+# 试运行(不写库)
+python -m etl_billiards.cli.main --dry-run --tasks DWD_LOAD_FROM_ODS
+```
+
+---
+
+## 8. 测试(ONLINE / OFFLINE)
+- `TEST_MODE=ONLINE`:调用真实 API,全链路 E/T/L。
+- `TEST_MODE=OFFLINE`:从 `TEST_JSON_ARCHIVE_DIR` 读取离线 JSON,只做 Transform + Load。
+- `TEST_DB_DSN`:如设置,则集成测试连真库;未设置用内存/临时库。
+示例:
+```bash
+TEST_MODE=ONLINE pytest tests/unit/test_etl_tasks_online.py
+TEST_MODE=OFFLINE TEST_JSON_ARCHIVE_DIR=tests/source-data-doc pytest tests/unit/test_etl_tasks_offline.py
+python scripts/test_db_connection.py --dsn postgresql://user:pwd@host:5432/db --query "SELECT 1"
+```
+
+---
+
+## 9. 开发与扩展
+- 新任务:在 `tasks/` 继承 BaseTask,实现 `get_task_code/execute`,并在 `orchestration/task_registry.py` 注册。
+- 新 Loader/Checker:参考 `loaders/`、`quality/` 复用批量 upsert/质检接口。
+- 配置:`config/defaults.py` + `.env` + CLI 叠加,新增配置需在 defaults 与 env_parser 中声明。
+
+---
+
+## 10. ODS 任务上线指引
+- 任务注册脚本:`etl_billiards/database/seed_ods_tasks.sql`(替换 store_id 后执行:`psql "$PG_DSN" -f ...`)。
+- 确认 `etl_admin.etl_task` 中已启用所需 ODS 任务。
+- 离线回放:可用 `scripts/rebuild_ods_from_json`(如有)从本地 JSON 重建 ODS。
+- 单测:`pytest etl_billiards/tests/unit/test_ods_tasks.py`。
+
+---
+
+## 11. ODS 表概览(数据路径)
+
+| ODS 表名 | 接口 Path | 数据列表路径 |
+| ------------------------------------ | ------------------------------------------------- | ----------------------------- |
+| assistant_accounts_master | /PersonnelManagement/SearchAssistantInfo | data.assistantInfos |
+| assistant_service_records | /AssistantPerformance/GetOrderAssistantDetails | data.orderAssistantDetails |
+| assistant_cancellation_records | /AssistantPerformance/GetAbolitionAssistant | data.abolitionAssistants |
+| goods_stock_movements | /GoodsStockManage/QueryGoodsOutboundReceipt | data.queryDeliveryRecordsList |
+| goods_stock_summary | /TenantGoods/GetGoodsStockReport | data |
+| group_buy_packages | /PackageCoupon/QueryPackageCouponList | data.packageCouponList |
+| group_buy_redemption_records | /Site/GetSiteTableUseDetails | data.siteTableUseDetailsList |
+| member_profiles | /MemberProfile/GetTenantMemberList | data.tenantMemberInfos |
+| member_balance_changes | /MemberProfile/GetMemberCardBalanceChange | data.tenantMemberCardLogs |
+| member_stored_value_cards | /MemberProfile/GetTenantMemberCardList | data.tenantMemberCards |
+| payment_transactions | /PayLog/GetPayLogListPage | data |
+| platform_coupon_redemption_records | /Promotion/GetOfflineCouponConsumePageList | data |
+| recharge_settlements | /Site/GetRechargeSettleList | data.settleList |
+| refund_transactions | /Order/GetRefundPayLogList | data |
+| settlement_records | /Site/GetAllOrderSettleList | data.settleList |
+| settlement_ticket_details | /Order/GetOrderSettleTicketNew | 完整 JSON |
+| site_tables_master | /Table/GetSiteTables | data.siteTables |
+| stock_goods_category_tree | /TenantGoodsCategory/QueryPrimarySecondaryCategory| data.goodsCategoryList |
+| store_goods_master | /TenantGoods/GetGoodsInventoryList | data.orderGoodsList |
+| store_goods_sales_records | /TenantGoods/GetGoodsSalesList | data.orderGoodsLedgers |
+| table_fee_discount_records | /Site/GetTaiFeeAdjustList | data.taiFeeAdjustInfos |
+| table_fee_transactions | /Site/GetSiteTableOrderDetails | data.siteTableUseDetailsList |
+| tenant_goods_master | /TenantGoods/QueryTenantGoods | data.tenantGoodsList |
+
+> 完整字段级映射见 `docs/` 与 ODS/DWD DDL。
+
+---
+
+## 12. DWD 维度与建模要点
+1. 颗粒一致、单一业务键:一张 DWD 表只承载一种业务事件/颗粒,避免混颗粒。
+2. 先理解业务链路,再建模;不要机械按 JSON 列表建表。
+3. 业务键统一:site_id、member_id、table_id、order_settle_id、order_trade_no 等必须一致命名。
+4. 保留明细,不过度汇总;聚合留到 DWS/报表。
+5. 清洗标准化同时保留溯源字段(源主键、时间、金额、payload)。
+6. 去嵌套与解耦:数组展开子行,重复 profile 提炼维度。
+7. 演进优先加列/加表,减少对已有表结构的破坏。
+
+---
+
+## 13. 当前状态(2025-12-09)
+- 示例 JSON 已全量灌入,DWD 行数与 ODS 对齐。
+- 分类维度已展平大类+子类:`dim_goods_category` 26 行(category_level/leaf 已赋值)。
+- 部分空字段源数据即为空,如需补值请先确认上游。
+
+---
+
+## 14. 可精简/归档
+- `tmp/`、`tmp/etl_billiards_misc/` 中草稿、旧备份、调试脚本仅供参考,不影响运行。
+- 根级保留必要文件(README、requirements、run_etl.*、.env/.env.example),其他临时文件已移至 tmp。
+
+---
+
+## 15. FAQ
+- 字段空值:若映射已存在且源列非空仍为空,再检查上游 JSON;维度 SCD2 按全量合并。
+- DSN/路径:确认 `.env` 中 `PG_DSN`、`INGEST_SOURCE_DIR` 与本地一致。
+- 新增任务:在 `tasks/` 实现并注册到 `task_registry.py`,必要时同步更新 DDL 与映射。
+- 权限/运行:检查网络、账号权限;脚本需执行权限(如 `chmod +x run_etl.sh`)。
+
+
+
+## 16.temp
+原来在 task_merged.py 里配置的 14 个任务中,有 11 个目前还没有在新项目里实现,对应的 loader / task 类也不存在。
+
+
+
+原脚本里“导出请求/响应 JSON 到本地目录、生成 manifest.json / ingest_report.json 并支持 offline 模式”的那一块逻辑,在新代码里还没有真正落地,只保留了配置字段和数据库字段,但没有实际写文件和离线装载的实现。
+
+
+丰富Pytest,进行分模块.分任务测试
+
+
+质量检查目前没有被“接入主流程”,内容也待完善,入库等问题?
+
+
diff --git a/etl_billiards/0.py b/tmp/etl_billiards_misc/0.py
similarity index 100%
rename from etl_billiards/0.py
rename to tmp/etl_billiards_misc/0.py
diff --git a/tmp/etl_billiards_misc/backups/manual_ingest_task.py b/tmp/etl_billiards_misc/backups/manual_ingest_task.py
new file mode 100644
index 0000000..f846718
--- /dev/null
+++ b/tmp/etl_billiards_misc/backups/manual_ingest_task.py
@@ -0,0 +1,321 @@
+# -*- coding: utf-8 -*-
+"""鎵嬪伐绀轰緥鏁版嵁鐏屽叆锛氭寜 schema_ODS_doc.sql 涓婚敭/鍞竴閿壒閲忓啓鍏?ODS銆?""
+from __future__ import annotations
+
+import json
+import os
+from datetime import datetime
+from typing import Any, Iterable
+
+from psycopg2.extras import Json
+
+from .base_task import BaseTask
+
+
+class ManualIngestTask(BaseTask):
+ """鏈湴绀轰緥 JSON 鐏屽叆 ODS锛岀‘淇濊〃鍚嶃€佷富閿€佹彃鍏ュ垪涓?schema_ODS_doc.sql 瀵归綈銆?""
+
+ def __init__(self, config, db_connection, api_client, logger):
+ """鍒濆鍖栫紦瀛橈紝閬垮厤閲嶅鏌ヨ琛ㄧ粨鏋勩€?""
+ super().__init__(config, db_connection, api_client, logger)
+ self._table_columns_cache: dict[str, list[str]] = {}
+
+ # 鏂囦欢鍏抽敭璇?-> 鐩爣琛紙鍖归厤 export/temp/source-data-doc 涓嬬ず鑼?JSON 鍚嶇О锛? FILE_MAPPING: list[tuple[tuple[str, ...], str]] = [
+ (("浼氬憳妗f", "member_profiles"), "billiards_ods.member_profiles"),
+ (("浣欓鍙樻洿璁板綍", "member_balance_changes"), "billiards_ods.member_balance_changes"),
+ (("鍌ㄥ€煎崱鍒楄〃", "member_stored_value_cards"), "billiards_ods.member_stored_value_cards"),
+ (("鍏呭€艰褰?, "recharge_settlements"), "billiards_ods.recharge_settlements"),
+ (("缁撹处璁板綍", "settlement_records"), "billiards_ods.settlement_records"),
+ (("鍔╂暀搴熼櫎", "assistant_cancellation_records"), "billiards_ods.assistant_cancellation_records"),
+ (("鍔╂暀璐﹀彿", "assistant_accounts_master"), "billiards_ods.assistant_accounts_master"),
+ (("鍔╂暀娴佹按", "assistant_service_records"), "billiards_ods.assistant_service_records"),
+ (("鍙版鍒楄〃", "site_tables_master"), "billiards_ods.site_tables_master"),
+ (("鍙拌垂鎵撴姌", "table_fee_discount_records"), "billiards_ods.table_fee_discount_records"),
+ (("鍙拌垂娴佹按", "table_fee_transactions"), "billiards_ods.table_fee_transactions"),
+ (("搴撳瓨鍙樺寲璁板綍1", "goods_stock_movements"), "billiards_ods.goods_stock_movements"),
+ (("搴撳瓨鍙樺寲璁板綍2", "stock_goods_category_tree"), "billiards_ods.stock_goods_category_tree"),
+ (("搴撳瓨姹囨€?, "goods_stock_summary"), "billiards_ods.goods_stock_summary"),
+ (("鏀粯璁板綍", "payment_transactions"), "billiards_ods.payment_transactions"),
+ (("閫€娆捐褰?, "refund_transactions"), "billiards_ods.refund_transactions"),
+ (("骞冲彴楠屽埜璁板綍", "platform_coupon_redemption_records"), "billiards_ods.platform_coupon_redemption_records"),
+ (("鍥㈣喘濂楅娴佹按", "group_buy_redemption_records"), "billiards_ods.group_buy_packages_ledger"),
+ (("鍥㈣喘濂楅", "group_buy_packages"), "billiards_ods.group_buy_packages"),
+ (("灏忕エ璇︽儏", "settlement_ticket_details"), "billiards_ods.settlement_ticket_details"),
+ (("闂ㄥ簵鍟嗗搧妗f", "store_goods_master"), "billiards_ods.store_goods_master"),
+ (("鍟嗗搧妗f", "tenant_goods_master"), "billiards_ods.tenant_goods_master"),
+ (("闂ㄥ簵鍟嗗搧閿€鍞褰?, "store_goods_sales_records"), "billiards_ods.store_goods_sales_records"),
+ ]
+
+ # 琛ㄧ粨鏋勮鏄庯細pk=涓婚敭鍒?None 琛ㄧず鏃犲啿绐佹洿鏂?锛宩son_cols=闇€瑕佸崟鍒楀瓨 JSONB 鐨勫瓧娈? TABLE_SPECS: dict[str, dict[str, Any]] = {
+ "billiards_ods.member_profiles": {"pk": "id"},
+ "billiards_ods.member_balance_changes": {"pk": "id"},
+ "billiards_ods.member_stored_value_cards": {"pk": "id"},
+ "billiards_ods.recharge_settlements": {"pk": None, "json_cols": ["settleList", "siteProfile"]},
+ "billiards_ods.settlement_records": {"pk": None, "json_cols": ["settleList", "siteProfile"]},
+ "billiards_ods.assistant_cancellation_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.assistant_accounts_master": {"pk": "id"},
+ "billiards_ods.assistant_service_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.site_tables_master": {"pk": "id"},
+ "billiards_ods.table_fee_discount_records": {"pk": "id", "json_cols": ["siteProfile", "tableProfile"]},
+ "billiards_ods.table_fee_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.goods_stock_movements": {"pk": "siteGoodsStockId"},
+ "billiards_ods.stock_goods_category_tree": {"pk": "id", "json_cols": ["categoryBoxes"]},
+ "billiards_ods.goods_stock_summary": {"pk": "siteGoodsId"},
+ "billiards_ods.payment_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.refund_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.platform_coupon_redemption_records": {"pk": "id"},
+ "billiards_ods.tenant_goods_master": {"pk": "id"},
+ "billiards_ods.group_buy_packages": {"pk": "id"},
+ "billiards_ods.group_buy_packages_ledger": {"pk": "id"},
+ "billiards_ods.settlement_ticket_details": {
+ "pk": "orderSettleId",
+ "json_cols": ["memberProfile", "orderItem", "tenantMemberCardLogs"],
+ },
+ "billiards_ods.store_goods_master": {"pk": "id"},
+ "billiards_ods.store_goods_sales_records": {"pk": "id"},
+ }
+
+ def get_task_code(self) -> str:
+ """杩斿洖浠诲姟缂栫爜銆?""
+ return "MANUAL_INGEST"
+
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ """浠庣ず鑼冪洰褰曡鍙?JSON锛屾寜琛?涓婚敭鎵归噺鍏ュ簱銆?""
+ data_dir = (
+ self.config.get("manual.data_dir")
+ or self.config.get("pipeline.ingest_source_dir")
+ or r"tests/testdata_json"
+ )
+ if not os.path.exists(data_dir):
+ self.logger.error("Data directory not found: %s", data_dir)
+ return {"status": "error", "message": "Directory not found"}
+
+ counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+
+ for filename in sorted(os.listdir(data_dir)):
+ if not filename.endswith(".json"):
+ continue
+ filepath = os.path.join(data_dir, filename)
+ try:
+ with open(filepath, "r", encoding="utf-8") as fh:
+ raw_entries = json.load(fh)
+ except Exception:
+ counts["errors"] += 1
+ self.logger.exception("Failed to read %s", filename)
+ continue
+
+ if not isinstance(raw_entries, list):
+ raw_entries = [raw_entries]
+
+ records = self._extract_records(raw_entries)
+ if not records:
+ counts["skipped"] += 1
+ continue
+
+ target_table = self._match_by_filename(filename)
+ if not target_table:
+ self.logger.warning("No mapping found for file: %s", filename)
+ counts["skipped"] += 1
+ continue
+
+ self.logger.info("Ingesting %s into %s", filename, target_table)
+ try:
+ inserted, updated = self._ingest_table(target_table, records, filename)
+ counts["inserted"] += inserted
+ counts["updated"] += updated
+ counts["fetched"] += len(records)
+ except Exception:
+ counts["errors"] += 1
+ self.logger.exception("Error processing %s", filename)
+ self.db.rollback()
+ continue
+
+ try:
+ self.db.commit()
+ except Exception:
+ self.db.rollback()
+ raise
+
+ return {"status": "SUCCESS", "counts": counts}
+
+ # ------------------------------------------------------------------ helpers
+ def _match_by_filename(self, filename: str) -> str | None:
+ """鏍规嵁鏂囦欢鍚嶅叧閿瘝鎵惧埌鐩爣琛ㄣ€?""
+ for keywords, table in self.FILE_MAPPING:
+ if any(keyword and keyword in filename for keyword in keywords):
+ return table
+ return None
+
+ def _extract_records(self, raw_entries: Iterable[Any]) -> list[dict]:
+ """鍏煎澶氱 JSON 缁撴瀯锛屾彁鍙栨垚璁板綍鍒楄〃銆?""
+ records: list[dict] = []
+ for entry in raw_entries:
+ if isinstance(entry, dict):
+ # 濡傛灉鍚?data 涓旇繕鍖呭惈鍏朵粬閿紙濡?orderSettleId锛夛紝浼樺厛淇濈暀澶栧眰浠ュ厤涓㈠け涓婚敭
+ preferred = entry
+ if "data" in entry and not any(k not in {"data", "code"} for k in entry.keys()):
+ preferred = entry["data"]
+ data = preferred
+ if isinstance(data, dict):
+ list_used = False
+ for v in data.values():
+ if isinstance(v, list) and v and isinstance(v[0], dict):
+ records.extend(v)
+ list_used = True
+ break
+ if list_used:
+ continue
+ if isinstance(data, list) and data and isinstance(data[0], dict):
+ records.extend(data)
+ elif isinstance(data, dict):
+ records.append(data)
+ elif isinstance(entry, list):
+ records.extend([item for item in entry if isinstance(item, dict)])
+ return records
+
+ def _get_table_columns(self, table: str) -> list[str]:
+ """鏌ヨ淇℃伅_schema锛岃幏鍙栫洰鏍囪〃鐨勫叏閮ㄥ垪鍚嶏紙鎸夐『搴忥級銆?""
+ if table in self._table_columns_cache:
+ return self._table_columns_cache[table]
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT column_name, data_type, udt_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """
+ with self.db.conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ cols = [(r[0], (r[1] or "").lower(), (r[2] or "").lower()) for r in cur.fetchall()]
+ self._table_columns_cache[table] = cols
+ return cols
+
+ def _ingest_table(self, table: str, records: list[dict], source_file: str) -> tuple[int, int]:
+ """鏋勯€?INSERT/ON CONFLICT 璇彞骞舵壒閲忔墽琛屻€?""
+ spec = self.TABLE_SPECS.get(table)
+ if not spec:
+ raise ValueError(f"No table spec for {table}")
+
+ pk_col = spec.get("pk")
+ json_cols = set(spec.get("json_cols", []))
+ json_cols_lower = {c.lower() for c in json_cols}
+
+ columns_info = self._get_table_columns(table)
+ columns = [c[0] for c in columns_info]
+ db_json_cols_lower = {
+ c[0].lower() for c in columns_info if c[1] in ("json", "jsonb") or c[2] in ("json", "jsonb")
+ }
+ pk_col_db = None
+ if pk_col:
+ pk_col_db = next((c for c in columns if c.lower() == pk_col.lower()), pk_col)
+
+ placeholders = ", ".join(["%s"] * len(columns))
+ col_list = ", ".join(f'"{c}"' for c in columns)
+ sql = f'INSERT INTO {table} ({col_list}) VALUES ({placeholders})'
+ if pk_col_db:
+ update_cols = [c for c in columns if c != pk_col_db]
+ set_clause = ", ".join(f'"{c}"=EXCLUDED."{c}"' for c in update_cols)
+ sql += f' ON CONFLICT ("{pk_col_db}") DO UPDATE SET {set_clause}'
+ sql += " RETURNING (xmax = 0) AS inserted"
+
+ params = []
+ now = datetime.now()
+ json_dump = lambda v: json.dumps(v, ensure_ascii=False) # noqa: E731
+ for rec in records:
+ merged_rec = rec if isinstance(rec, dict) else {}
+ # 閫愬眰灞曞紑 data -> data.data 缁撴瀯锛屽~鍏呯己澶卞瓧娈? data_part = merged_rec.get("data")
+ while isinstance(data_part, dict):
+ merged_rec = {**data_part, **merged_rec}
+ data_part = data_part.get("data")
+
+ pk_val = self._get_value_case_insensitive(merged_rec, pk_col) if pk_col else None
+ if pk_col and (pk_val is None or pk_val == ""):
+ continue
+
+ row_vals = []
+ for col_name, data_type, udt in columns_info:
+ col_lower = col_name.lower()
+ if col_lower == "payload":
+ row_vals.append(Json(rec, dumps=json_dump))
+ continue
+ if col_lower == "source_file":
+ row_vals.append(source_file)
+ continue
+ if col_lower == "fetched_at":
+ row_vals.append(merged_rec.get(col_name, now))
+ continue
+
+ value = self._normalize_scalar(self._get_value_case_insensitive(merged_rec, col_name))
+
+ if col_lower in json_cols_lower or col_lower in db_json_cols_lower:
+ row_vals.append(Json(value, dumps=json_dump) if value is not None else None)
+ continue
+
+ casted = self._cast_value(value, data_type)
+ row_vals.append(casted)
+ params.append(tuple(row_vals))
+
+ if not params:
+ return 0, 0
+
+ inserted = 0
+ updated = 0
+ with self.db.conn.cursor() as cur:
+ for row in params:
+ cur.execute(sql, row)
+ try:
+ flag = cur.fetchone()[0]
+ except Exception:
+ flag = None
+ if flag:
+ inserted += 1
+ else:
+ updated += 1
+ return inserted, updated
+
+ def _get_value_case_insensitive(self, record: dict, col: str):
+ """蹇界暐澶у皬鍐欒幏鍙栧€硷紝鍏煎 information_schema 灏忓啓鍒楀悕涓?JSON 鍘熷澶у皬鍐欍€?""
+ if record is None:
+ return None
+ if col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+ def _normalize_scalar(self, value):
+ """灏嗙┖瀛楃涓叉爣鍑嗗寲涓?None锛岄伩鍏嶆暟鍊?鏃堕棿瀛楁绫诲瀷閿欒銆?""
+ if value == "" or value == "{}" or value == "[]":
+ return None
+ return value
+
+ def _cast_value(self, value, data_type: str):
+ """鏍规嵁鍒楃被鍨嬪仛杞婚噺杞崲锛岄伩鍏嶇被鍨嬩笉鍖归厤銆?""
+ if value is None:
+ return None
+ dt = (data_type or "").lower()
+ if dt in ("integer", "bigint", "smallint"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return int(value)
+ except Exception:
+ return None
+ if dt in ("numeric", "double precision", "real", "decimal"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return float(value)
+ except Exception:
+ return None
+ if dt.startswith("timestamp") or dt in ("date", "time", "interval"):
+ # 浠呮帴鍙楀瓧绗︿覆/鏃ユ湡锛屾暟鍊肩瓑涓€寰嬬疆绌? return value if isinstance(value, str) else None
+ return value
+
diff --git a/tmp/etl_billiards_misc/backups/manual_ingest_task.py.bak_20251209 b/tmp/etl_billiards_misc/backups/manual_ingest_task.py.bak_20251209
new file mode 100644
index 0000000..874a295
--- /dev/null
+++ b/tmp/etl_billiards_misc/backups/manual_ingest_task.py.bak_20251209
@@ -0,0 +1,347 @@
+# -*- coding: utf-8 -*-
+"""手工示例数据灌入:按 schema_ODS_doc.sql 的表结构写入 ODS。"""
+from __future__ import annotations
+
+import json
+import os
+from datetime import datetime
+from typing import Any, Iterable
+
+from psycopg2.extras import Json
+
+from .base_task import BaseTask
+
+
+class ManualIngestTask(BaseTask):
+ """本地示例 JSON 灌入 ODS,确保表名/主键/插入列与 schema_ODS_doc.sql 对齐。"""
+
+ FILE_MAPPING: list[tuple[tuple[str, ...], str]] = [
+ (("member_profiles",), "billiards_ods.member_profiles"),
+ (("member_balance_changes",), "billiards_ods.member_balance_changes"),
+ (("member_stored_value_cards",), "billiards_ods.member_stored_value_cards"),
+ (("recharge_settlements",), "billiards_ods.recharge_settlements"),
+ (("settlement_records",), "billiards_ods.settlement_records"),
+ (("assistant_cancellation_records",), "billiards_ods.assistant_cancellation_records"),
+ (("assistant_accounts_master",), "billiards_ods.assistant_accounts_master"),
+ (("assistant_service_records",), "billiards_ods.assistant_service_records"),
+ (("site_tables_master",), "billiards_ods.site_tables_master"),
+ (("table_fee_discount_records",), "billiards_ods.table_fee_discount_records"),
+ (("table_fee_transactions",), "billiards_ods.table_fee_transactions"),
+ (("goods_stock_movements",), "billiards_ods.goods_stock_movements"),
+ (("stock_goods_category_tree",), "billiards_ods.stock_goods_category_tree"),
+ (("goods_stock_summary",), "billiards_ods.goods_stock_summary"),
+ (("payment_transactions",), "billiards_ods.payment_transactions"),
+ (("refund_transactions",), "billiards_ods.refund_transactions"),
+ (("platform_coupon_redemption_records",), "billiards_ods.platform_coupon_redemption_records"),
+ (("group_buy_redemption_records",), "billiards_ods.group_buy_redemption_records"),
+ (("group_buy_packages",), "billiards_ods.group_buy_packages"),
+ (("settlement_ticket_details",), "billiards_ods.settlement_ticket_details"),
+ (("store_goods_master",), "billiards_ods.store_goods_master"),
+ (("tenant_goods_master",), "billiards_ods.tenant_goods_master"),
+ (("store_goods_sales_records",), "billiards_ods.store_goods_sales_records"),
+ ]
+
+ TABLE_SPECS: dict[str, dict[str, Any]] = {
+ "billiards_ods.member_profiles": {"pk": "id"},
+ "billiards_ods.member_balance_changes": {"pk": "id"},
+ "billiards_ods.member_stored_value_cards": {"pk": "id"},
+ "billiards_ods.recharge_settlements": {"pk": "id"},
+ "billiards_ods.settlement_records": {"pk": "id"},
+ "billiards_ods.assistant_cancellation_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.assistant_accounts_master": {"pk": "id"},
+ "billiards_ods.assistant_service_records": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.site_tables_master": {"pk": "id"},
+ "billiards_ods.table_fee_discount_records": {"pk": "id", "json_cols": ["siteProfile", "tableProfile"]},
+ "billiards_ods.table_fee_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.goods_stock_movements": {"pk": "siteGoodsStockId"},
+ "billiards_ods.stock_goods_category_tree": {"pk": "id", "json_cols": ["categoryBoxes"]},
+ "billiards_ods.goods_stock_summary": {"pk": "siteGoodsId"},
+ "billiards_ods.payment_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.refund_transactions": {"pk": "id", "json_cols": ["siteProfile"]},
+ "billiards_ods.platform_coupon_redemption_records": {"pk": "id"},
+ "billiards_ods.tenant_goods_master": {"pk": "id"},
+ "billiards_ods.group_buy_packages": {"pk": "id"},
+ "billiards_ods.group_buy_redemption_records": {"pk": "id"},
+ "billiards_ods.settlement_ticket_details": {
+ "pk": "orderSettleId",
+ "json_cols": ["memberProfile", "orderItem", "tenantMemberCardLogs"],
+ },
+ "billiards_ods.store_goods_master": {"pk": "id"},
+ "billiards_ods.store_goods_sales_records": {"pk": "id"},
+ }
+
+ def get_task_code(self) -> str:
+ """返回任务编码。"""
+ return "MANUAL_INGEST"
+
+ def execute(self, cursor_data: dict | None = None) -> dict:
+ """从目录读取 JSON,按表定义批量入库。"""
+ data_dir = (
+ self.config.get("manual.data_dir")
+ or self.config.get("pipeline.ingest_source_dir")
+ or r"tests/testdata_json"
+ )
+ if not os.path.exists(data_dir):
+ self.logger.error("Data directory not found: %s", data_dir)
+ return {"status": "error", "message": "Directory not found"}
+
+ counts = {"fetched": 0, "inserted": 0, "updated": 0, "skipped": 0, "errors": 0}
+
+ for filename in sorted(os.listdir(data_dir)):
+ if not filename.endswith(".json"):
+ continue
+ filepath = os.path.join(data_dir, filename)
+ try:
+ with open(filepath, "r", encoding="utf-8") as fh:
+ raw_entries = json.load(fh)
+ except Exception:
+ counts["errors"] += 1
+ self.logger.exception("Failed to read %s", filename)
+ continue
+
+ entries = raw_entries if isinstance(raw_entries, list) else [raw_entries]
+ records = self._extract_records(entries)
+ if not records:
+ counts["skipped"] += 1
+ continue
+
+ target_table = self._match_by_filename(filename)
+ if not target_table:
+ self.logger.warning("No mapping found for file: %s", filename)
+ counts["skipped"] += 1
+ continue
+
+ self.logger.info("Ingesting %s into %s", filename, target_table)
+ try:
+ inserted, updated = self._ingest_table(target_table, records, filename)
+ counts["inserted"] += inserted
+ counts["updated"] += updated
+ counts["fetched"] += len(records)
+ except Exception:
+ counts["errors"] += 1
+ self.logger.exception("Error processing %s", filename)
+ self.db.rollback()
+ continue
+
+ try:
+ self.db.commit()
+ except Exception:
+ self.db.rollback()
+ raise
+
+ return {"status": "SUCCESS", "counts": counts}
+
+ def _match_by_filename(self, filename: str) -> str | None:
+ """根据文件名关键字匹配目标表。"""
+ for keywords, table in self.FILE_MAPPING:
+ if any(keyword and keyword in filename for keyword in keywords):
+ return table
+ return None
+
+ def _extract_records(self, raw_entries: Iterable[Any]) -> list[dict]:
+ """兼容多层 data/list 包装,抽取记录列表。"""
+ records: list[dict] = []
+ for entry in raw_entries:
+ if isinstance(entry, dict):
+ preferred = entry
+ if "data" in entry and not any(k not in {"data", "code"} for k in entry.keys()):
+ preferred = entry["data"]
+ data = preferred
+ if isinstance(data, dict):
+ # 特殊处理 settleList(充值、结算记录):展开 data.settleList 下的 settleList,抛弃上层 siteProfile
+ if "settleList" in data:
+ settle_list_val = data.get("settleList")
+ if isinstance(settle_list_val, dict):
+ settle_list_iter = [settle_list_val]
+ elif isinstance(settle_list_val, list):
+ settle_list_iter = settle_list_val
+ else:
+ settle_list_iter = []
+
+ handled = False
+ for item in settle_list_iter or []:
+ if not isinstance(item, dict):
+ continue
+ inner = item.get("settleList")
+ merged = dict(inner) if isinstance(inner, dict) else dict(item)
+ # 保留 siteProfile 供后续字段补充,但不落库
+ site_profile = data.get("siteProfile")
+ if isinstance(site_profile, dict):
+ merged.setdefault("siteProfile", site_profile)
+ records.append(merged)
+ handled = True
+ if handled:
+ continue
+
+ list_used = False
+ for v in data.values():
+ if isinstance(v, list) and v and isinstance(v[0], dict):
+ records.extend(v)
+ list_used = True
+ break
+ if list_used:
+ continue
+ if isinstance(data, list) and data and isinstance(data[0], dict):
+ records.extend(data)
+ elif isinstance(data, dict):
+ records.append(data)
+ elif isinstance(entry, list):
+ records.extend([item for item in entry if isinstance(item, dict)])
+ return records
+
+ def _get_table_columns(self, table: str) -> list[tuple[str, str, str]]:
+ """查询 information_schema,获取目标表列信息。"""
+ cache = getattr(self, "_table_columns_cache", {})
+ if table in cache:
+ return cache[table]
+ if "." in table:
+ schema, name = table.split(".", 1)
+ else:
+ schema, name = "public", table
+ sql = """
+ SELECT column_name, data_type, udt_name
+ FROM information_schema.columns
+ WHERE table_schema = %s AND table_name = %s
+ ORDER BY ordinal_position
+ """
+ with self.db.conn.cursor() as cur:
+ cur.execute(sql, (schema, name))
+ cols = [(r[0], (r[1] or "").lower(), (r[2] or "").lower()) for r in cur.fetchall()]
+ cache[table] = cols
+ self._table_columns_cache = cache
+ return cols
+
+ def _ingest_table(self, table: str, records: list[dict], source_file: str) -> tuple[int, int]:
+ """构建 INSERT/ON CONFLICT 语句并批量执行。"""
+ spec = self.TABLE_SPECS.get(table)
+ if not spec:
+ raise ValueError(f"No table spec for {table}")
+
+ pk_col = spec.get("pk")
+ json_cols = set(spec.get("json_cols", []))
+ json_cols_lower = {c.lower() for c in json_cols}
+
+ columns_info = self._get_table_columns(table)
+ columns = [c[0] for c in columns_info]
+ db_json_cols_lower = {
+ c[0].lower() for c in columns_info if c[1] in ("json", "jsonb") or c[2] in ("json", "jsonb")
+ }
+ pk_col_db = None
+ if pk_col:
+ pk_col_db = next((c for c in columns if c.lower() == pk_col.lower()), pk_col)
+
+ placeholders = ", ".join(["%s"] * len(columns))
+ col_list = ", ".join(f'"{c}"' for c in columns)
+ sql = f'INSERT INTO {table} ({col_list}) VALUES ({placeholders})'
+ if pk_col_db:
+ update_cols = [c for c in columns if c != pk_col_db]
+ set_clause = ", ".join(f'"{c}"=EXCLUDED."{c}"' for c in update_cols)
+ sql += f' ON CONFLICT ("{pk_col_db}") DO UPDATE SET {set_clause}'
+ sql += " RETURNING (xmax = 0) AS inserted"
+
+ params = []
+ now = datetime.now()
+ json_dump = lambda v: json.dumps(v, ensure_ascii=False) # noqa: E731
+ for rec in records:
+ merged_rec = rec if isinstance(rec, dict) else {}
+ data_part = merged_rec.get("data")
+ while isinstance(data_part, dict):
+ merged_rec = {**data_part, **merged_rec}
+ data_part = data_part.get("data")
+
+ # 针对充值/结算,补齐 siteProfile 中的店铺信息
+ if table in {
+ "billiards_ods.recharge_settlements",
+ "billiards_ods.settlement_records",
+ }:
+ site_profile = merged_rec.get("siteProfile") or merged_rec.get("site_profile")
+ if isinstance(site_profile, dict):
+ merged_rec.setdefault("tenantid", site_profile.get("tenant_id") or site_profile.get("tenantId"))
+ merged_rec.setdefault("siteid", site_profile.get("id") or site_profile.get("siteId"))
+ merged_rec.setdefault("sitename", site_profile.get("shop_name") or site_profile.get("siteName"))
+
+ pk_val = self._get_value_case_insensitive(merged_rec, pk_col) if pk_col else None
+ if pk_col and (pk_val is None or pk_val == ""):
+ continue
+
+ row_vals = []
+ for col_name, data_type, udt in columns_info:
+ col_lower = col_name.lower()
+ if col_lower == "payload":
+ row_vals.append(Json(rec, dumps=json_dump))
+ continue
+ if col_lower == "source_file":
+ row_vals.append(source_file)
+ continue
+ if col_lower == "fetched_at":
+ row_vals.append(merged_rec.get(col_name, now))
+ continue
+
+ value = self._normalize_scalar(self._get_value_case_insensitive(merged_rec, col_name))
+
+ if col_lower in json_cols_lower or col_lower in db_json_cols_lower:
+ row_vals.append(Json(value, dumps=json_dump) if value is not None else None)
+ continue
+
+ casted = self._cast_value(value, data_type)
+ row_vals.append(casted)
+ params.append(tuple(row_vals))
+
+ if not params:
+ return 0, 0
+
+ inserted = 0
+ updated = 0
+ with self.db.conn.cursor() as cur:
+ for row in params:
+ cur.execute(sql, row)
+ flag = cur.fetchone()[0]
+ if flag:
+ inserted += 1
+ else:
+ updated += 1
+ return inserted, updated
+
+ @staticmethod
+ def _get_value_case_insensitive(record: dict, col: str | None):
+ """忽略大小写获取值,兼容 information_schema 与 JSON 原始字段。"""
+ if record is None or col is None:
+ return None
+ if col in record:
+ return record.get(col)
+ col_lower = col.lower()
+ for k, v in record.items():
+ if isinstance(k, str) and k.lower() == col_lower:
+ return v
+ return None
+
+ @staticmethod
+ def _normalize_scalar(value):
+ """将空字符串/空 JSON 规范为 None,避免类型转换错误。"""
+ if value == "" or value == "{}" or value == "[]":
+ return None
+ return value
+
+ @staticmethod
+ def _cast_value(value, data_type: str):
+ """根据列类型做简单转换,保证批量插入兼容。"""
+ if value is None:
+ return None
+ dt = (data_type or "").lower()
+ if dt in ("integer", "bigint", "smallint"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return int(value)
+ except Exception:
+ return None
+ if dt in ("numeric", "double precision", "real", "decimal"):
+ if isinstance(value, bool):
+ return int(value)
+ try:
+ return float(value)
+ except Exception:
+ return None
+ if dt.startswith("timestamp") or dt in ("date", "time", "interval"):
+ return value if isinstance(value, str) else None
+ return value
diff --git a/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql b/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql
new file mode 100644
index 0000000..73d3307
--- /dev/null
+++ b/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql
@@ -0,0 +1,1714 @@
+-- 鏂囦欢璇存槑锛歄DS 灞?DDL锛屾寜绀鸿寖 JSON锛圕:\dev\LLTQ\export\temp\source-data-doc锛夌敓鎴愶紝瀛楁鍚嶄笌婧?JSON 涓€鑷翠究浜庤拷婧€?
+-- 澶囨敞鍧囦娇鐢ㄤ腑鏂囷紝鏍囨敞鏉ユ簮瀛楁璺緞鍙婂惈涔夛紱鏈睍寮€鐨勫祵濂楀瓧娈典互 JSONB 鍏ㄩ噺淇濈暀銆?
+-- 鎵€鏈夊瓧娈靛娉ㄥ潎鏍囨敞鏉ユ簮JSON璺緞涓庝腑鏂囧惈涔夛紙鍚箟鍙傝€冨搴旂殑鈥滃瓧娈典笌鍏崇郴鍒嗘瀽鈥滿D锛夈€?
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+-- ========== 浼氬憳妗f锛堜細鍛樻。妗?json -> data.tenantMemberInfos锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.member_profiles IS '鏉ユ簮锛氫細鍛樻。妗?json -> data.tenantMemberInfos锛涙瘡鏉¤褰曟槸浼氬憳鍦ㄧ鎴蜂笅鐨勫崱妗f锛堜細鍛樏楀崱绉嶏級銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '鏉ユ簮:data.tenantMemberInfos.tenant_id锛涚鎴?鍝佺墝ID銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '鏉ユ簮:data.tenantMemberInfos.register_site_id锛涗細鍛樻敞鍐岄棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '鏉ユ簮:data.tenantMemberInfos.site_name锛涙敞鍐岄棬搴楀悕绉板揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '鏉ユ簮:data.tenantMemberInfos.id锛涗細鍛樿处鎴蜂富閿紙绉熸埛鍐呬竴寮犲崱/涓€涓处鎴凤級銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '鏉ユ簮:data.tenantMemberInfos.system_member_id锛涘钩鍙扮骇浼氬憳ID锛岀敤浜庤法搴?璺ㄥ崱鑱氬悎鍚屼竴浼氬憳銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '鏉ユ簮:data.tenantMemberInfos.member_card_grade_code锛涗細鍛樺崱绉?绛夌骇缂栫爜锛堝鍌ㄥ€煎崱/鍙拌垂鍗$瓑锛夈€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '鏉ユ簮:data.tenantMemberInfos.member_card_grade_name锛涗細鍛樺崱绉?绛夌骇鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '鏉ユ簮:data.tenantMemberInfos.mobile锛涗細鍛樻墜鏈哄彿銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '鏉ユ簮:data.tenantMemberInfos.nickname锛涗細鍛樻樀绉?灞曠ず鍚嶃€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '鏉ユ簮:data.tenantMemberInfos.point锛涘綋鍓嶇Н鍒嗕綑棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '鏉ユ簮:data.tenantMemberInfos.growth_value锛涙垚闀垮€?缁忛獙鍊笺€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '鏉ユ簮:data.tenantMemberInfos.referrer_member_id锛涙帹鑽愪汉浼氬憳ID锛? 琛ㄧず鏃狅級銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '鏉ユ簮:data.tenantMemberInfos.status锛涘崱璐︽埛鐘舵€佹灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '鏉ユ簮:data.tenantMemberInfos.user_status锛涚敤鎴风姸鎬佹灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '鏉ユ簮:data.tenantMemberInfos.create_time锛涜处鎴峰垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欐湭灞曞紑瀛楁銆?;
+
+-- ========== 浣欓鍙樻洿璁板綍锛堜綑棰濆彉鏇磋褰?json -> data.tenantMemberCardLogs锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '鏉ユ簮锛氫綑棰濆彉鏇磋褰?json -> data.tenantMemberCardLogs锛涜褰曚細鍛樺崱浣欓姣忔鍙樻洿銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '鏉ユ簮:data.tenantMemberCardLogs.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '鏉ユ簮:data.tenantMemberCardLogs.site_id锛涘彂鐢熷彉鏇寸殑闂ㄥ簵ID銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '鏉ユ簮:data.tenantMemberCardLogs.register_site_id锛涘紑鍗?娉ㄥ唽闂ㄥ簵ID銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '鏉ユ簮:data.tenantMemberCardLogs.registerSiteName锛涙敞鍐岄棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '鏉ユ簮:data.tenantMemberCardLogs.paySiteName锛涙敮浠樺彂鐢熼棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '鏉ユ簮:data.tenantMemberCardLogs.id锛涗綑棰濆彉鏇磋褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '鏉ユ簮:data.tenantMemberCardLogs.tenant_member_id锛涚鎴峰唴浼氬憳ID銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '鏉ユ簮:data.tenantMemberCardLogs.tenant_member_card_id锛涗細鍛樺崱璐︽埛ID銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '鏉ユ簮:data.tenantMemberCardLogs.system_member_id锛涘钩鍙颁細鍛業D銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '鏉ユ簮:data.tenantMemberCardLogs.memberName锛涗細鍛樺鍚?鏄电О蹇収銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '鏉ユ簮:data.tenantMemberCardLogs.memberMobile锛涗細鍛樻墜鏈哄彿蹇収銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '鏉ユ簮:data.tenantMemberCardLogs.card_type_id锛涘崱绉岻D銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '鏉ユ簮:data.tenantMemberCardLogs.memberCardTypeName锛涘崱绉嶅悕绉般€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '鏉ユ簮:data.tenantMemberCardLogs.account_data锛涙湰娆″彉鍔ㄩ噾棰濓紝姝d负澧炲姞銆佽礋涓哄噺灏戙€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '鏉ユ簮:data.tenantMemberCardLogs.before锛涘彉鏇村墠浣欓銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '鏉ユ簮:data.tenantMemberCardLogs.after锛涘彉鏇村悗浣欓銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '鏉ユ簮:data.tenantMemberCardLogs.refund_amount锛涙湰娆℃秹鍙婇€€娆鹃噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '鏉ユ簮:data.tenantMemberCardLogs.from_type锛涘彉鏇存潵婧愮被鍨嬫灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '鏉ユ簮:data.tenantMemberCardLogs.payment_method锛涙敮浠樻柟寮忔灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '鏉ユ簮:data.tenantMemberCardLogs.relate_id锛涗笟鍔″叧鑱擨D锛堝璁㈠崟/缁撶畻鍗曪級銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '鏉ユ簮:data.tenantMemberCardLogs.remark锛涘娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '鏉ユ簮:data.tenantMemberCardLogs.operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '鏉ユ簮:data.tenantMemberCardLogs.operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '鏉ユ簮:data.tenantMemberCardLogs.is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '鏉ユ簮:data.tenantMemberCardLogs.create_time锛涜褰曞垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欐湭灞曞紑瀛楁銆?;
+
+-- ========== 鍌ㄥ€煎崱鍒楄〃锛堝偍鍊煎崱鍒楄〃.json -> data.tenantMemberCards锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '鏉ユ簮锛氬偍鍊煎崱鍒楄〃.json -> data.tenantMemberCards锛涘寘鍚偍鍊煎崱/鍙拌垂鍗?娲诲姩鍒哥瓑鍗″畾涔夊強鎶樻墸閰嶇疆銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '鏉ユ簮:data.tenantMemberCards.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '鏉ユ簮:data.tenantMemberCards.tenant_member_id锛涚鎴峰唴浼氬憳ID銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '鏉ユ簮:data.tenantMemberCards.system_member_id锛涘钩鍙颁細鍛業D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '鏉ユ簮:data.tenantMemberCards.register_site_id锛涘紑鍗¢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '鏉ユ簮:data.tenantMemberCards.site_name锛涘紑鍗¢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '鏉ユ簮:data.tenantMemberCards.id锛涗細鍛樺崱璐︽埛ID銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '鏉ユ簮:data.tenantMemberCards.member_card_grade_code锛涘崱绉?绛夌骇缂栫爜銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '鏉ユ簮:data.tenantMemberCards.member_card_grade_code_name锛涘崱绉?绛夌骇鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '鏉ユ簮:data.tenantMemberCards.member_card_type_name锛涘崱绫诲瀷鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '鏉ユ簮:data.tenantMemberCards.member_name锛涗細鍛樺鍚嶅揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '鏉ユ簮:data.tenantMemberCards.member_mobile锛涗細鍛樻墜鏈哄彿蹇収銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '鏉ユ簮:data.tenantMemberCards.card_type_id锛涘崱绫诲瀷ID銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '鏉ユ簮:data.tenantMemberCards.card_no锛涘疄浣?铏氭嫙鍗″彿銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '鏉ユ簮:data.tenantMemberCards.card_physics_type锛涚墿鐞嗗崱绫诲瀷鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '鏉ユ簮:data.tenantMemberCards.balance锛涘崱鍐呭綋鍓嶄綑棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '鏉ユ簮:data.tenantMemberCards.denomination锛涘崱闈㈤/鍒濆鍌ㄥ€奸噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '鏉ユ簮:data.tenantMemberCards.table_discount锛涘彴璐规姌鎵o紝10琛ㄧず涓嶆墦鎶樸€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '鏉ユ簮:data.tenantMemberCards.goods_discount锛涘晢鍝佹姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '鏉ユ簮:data.tenantMemberCards.assistant_discount锛涘姪鏁欐湇鍔℃姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '鏉ユ簮:data.tenantMemberCards.assistant_reward_discount锛涘姪鏁欏鍔遍噾鎶樻墸銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '鏉ユ簮:data.tenantMemberCards.table_service_discount锛涘彴鐞冩湇鍔℃姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '鏉ユ簮:data.tenantMemberCards.assistant_service_discount锛涘姪鏁欐湇鍔℃姌鎵o紙鍙︿竴鍙e緞锛夈€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '鏉ユ簮:data.tenantMemberCards.coupon_discount锛涘埜绫绘姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '鏉ユ簮:data.tenantMemberCards.goods_service_discount锛涘晢鍝佹湇鍔℃姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '鏉ユ簮:data.tenantMemberCards.assistant_discount_sub_switch锛涘姪鏁欐姌鎵e紑鍏炽€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '鏉ユ簮:data.tenantMemberCards.table_discount_sub_switch锛涘彴璐规姌鎵e紑鍏炽€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '鏉ユ簮:data.tenantMemberCards.goods_discount_sub_switch锛涘晢鍝佹姌鎵e紑鍏炽€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '鏉ユ簮:data.tenantMemberCards.assistant_reward_discount_sub_switch锛涘姪鏁欏鍔辨姌鎵e紑鍏炽€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.table_service_deduct_radio锛涘彴璐规姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.assistant_service_deduct_radio锛涘姪鏁欐湇鍔℃姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.goods_service_deduct_radio锛涘晢鍝佹湇鍔℃姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.assistant_deduct_radio锛涘姪鏁欐姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.table_deduct_radio锛涘彴璐规姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.goods_deduct_radio锛涘晢鍝佹姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.coupon_deduct_radio锛涘埜鎶垫墸姣斾緥銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '鏉ユ簮:data.tenantMemberCards.assistant_reward_deduct_radio锛涘姪鏁欏鍔辨姷鎵f瘮渚嬨€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '鏉ユ簮:data.tenantMemberCards.tableCardDeduct锛涘彴璐规姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '鏉ユ簮:data.tenantMemberCards.tableServiceCardDeduct锛涘彴鐞冩湇鍔℃姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '鏉ユ簮:data.tenantMemberCards.goodsCarDeduct锛涘晢鍝佹姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '鏉ユ簮:data.tenantMemberCards.goodsServiceCardDeduct锛涘晢鍝佹湇鍔℃姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '鏉ユ簮:data.tenantMemberCards.assistantCardDeduct锛涘姪鏁欐姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '鏉ユ簮:data.tenantMemberCards.assistantServiceCardDeduct锛涘姪鏁欐湇鍔℃姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '鏉ユ簮:data.tenantMemberCards.assistantRewardCardDeduct锛涘姪鏁欏鍔辨姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '鏉ユ簮:data.tenantMemberCards.cardSettleDeduct锛涚粨绠楁姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '鏉ユ簮:data.tenantMemberCards.couponCardDeduct锛涘埜鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '鏉ユ簮:data.tenantMemberCards.deliveryFeeDeduct锛涢厤閫佽垂鐢ㄦ姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '鏉ユ簮:data.tenantMemberCards.use_scene锛涗娇鐢ㄥ満鏅灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '鏉ユ簮:data.tenantMemberCards.able_cross_site锛涙槸鍚﹁法搴楅€氱敤銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '鏉ユ簮:data.tenantMemberCards.able_site_transfer锛涙槸鍚﹀彲闂ㄥ簵杞Щ銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '鏉ユ簮:data.tenantMemberCards.is_allow_give锛涙槸鍚﹀厑璁歌浆璧犮€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '鏉ユ簮:data.tenantMemberCards.is_allow_order_deduct锛涙槸鍚﹀厑璁歌鍗曟姷鎵c€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '鏉ユ簮:data.tenantMemberCards.is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '鏉ユ簮:data.tenantMemberCards.bind_password锛涙槸鍚︾粦瀹氬瘑鐮?缁戝畾瀵嗙爜鍐呭銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '鏉ユ簮:data.tenantMemberCards.goods_discount_range_type锛涘晢鍝佹姌鎵i€傜敤鑼冨洿绫诲瀷銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '鏉ユ簮:data.tenantMemberCards.goods_discount_sub_switch锛涘晢鍝佹姌鎵e紑鍏炽€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '鏉ユ簮:data.tenantMemberCards.goodsCategoryId锛涘晢鍝佸垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '鏉ユ簮:data.tenantMemberCards.tableAreaId锛涘彴鐞冨尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '鏉ユ簮:data.tenantMemberCards.effect_site_id锛涚敓鏁堥棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '鏉ユ簮:data.tenantMemberCards.start_time锛涙湁鏁堟湡寮€濮嬫椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '鏉ユ簮:data.tenantMemberCards.end_time锛涙湁鏁堟湡缁撴潫鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '鏉ユ簮:data.tenantMemberCards.disable_start_time锛涘仠鐢ㄥ紑濮嬫椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '鏉ユ簮:data.tenantMemberCards.disable_end_time锛涘仠鐢ㄧ粨鏉熸椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '鏉ユ簮:data.tenantMemberCards.last_consume_time锛涙渶杩戞秷璐规椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '鏉ユ簮:data.tenantMemberCards.create_time锛涘崱鍒涘缓鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '鏉ユ簮:data.tenantMemberCards.status锛涘崱鐘舵€併€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '鏉ユ簮:data.tenantMemberCards.sort锛涙帓搴忓瓧娈点€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '鏉ユ簮:data.tenantMemberCards.tenantAvatar锛涚鎴峰ご鍍廢RL銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '鏉ユ簮:data.tenantMemberCards.tenantName锛涚鎴峰悕绉般€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '鏉ユ簮:data.tenantMemberCards.pdAssisnatLevel锛涘姪鏁欑瓑绾э紙鍏呭€艰禒閫侀厤缃級銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '鏉ユ簮:data.tenantMemberCards.cxAssisnatLevel锛涘姪鏁欑瓑绾э紙鎸佺画娑堣垂閰嶇疆锛夈€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欐湭灞曞紑瀛楁銆?;
+
+-- ========== 鍏呭€艰褰曪紙鍏呭€艰褰?json -> data.settleList[] = {settleList, siteProfile}锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ recharge_order_id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_name_snapshot TEXT,
+ member_id BIGINT,
+ member_name_snapshot TEXT,
+ member_phone_snapshot TEXT,
+ tenant_member_card_id BIGINT,
+ member_card_type_name TEXT,
+ settle_relate_id BIGINT,
+ settle_type INT,
+ settle_name TEXT,
+ is_first INT,
+ settle_status INT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ payment_method INT,
+ can_be_revoked BOOLEAN,
+ is_bind_member BOOLEAN,
+ is_activity BOOLEAN,
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ operator_id BIGINT,
+ operator_name_snapshot TEXT,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ order_remark TEXT,
+ table_id BIGINT,
+ serial_number BIGINT,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ site_profile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.recharge_settlements IS '???????.json -> data.settleList[]?? settleList ???????site_profile ???????payload ???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.recharge_order_id IS '??:settleList.id???/????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenant_id IS '??:settleList.tenantId???ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.site_id IS '??:settleList.siteId???ID????? siteProfile.id??';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.site_name_snapshot IS '??:siteProfile.shop_name ????? settleList.siteName?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.member_id IS '??:settleList.memberId?????ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.member_name_snapshot IS '??:settleList.memberName????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.member_phone_snapshot IS '??:settleList.memberPhone?????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenant_member_card_id IS '??:settleList.tenantMemberCardId??????ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.member_card_type_name IS '??:settleList.memberCardTypeName?????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settle_relate_id IS '??:settleList.settleRelateId?????ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settle_type IS '??:settleList.settleType?5=?????7=?????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settle_name IS '??:settleList.settleName????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.is_first IS '??:settleList.isFirst????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settle_status IS '??:settleList.settleStatus??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pay_amount IS '??:settleList.payAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refund_amount IS '??:settleList.refundAmount??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.point_amount IS '??:settleList.pointAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cash_amount IS '??:settleList.cashAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.online_amount IS '??:settleList.onlineAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balance_amount IS '??:settleList.balanceAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.card_amount IS '??:settleList.cardAmount?????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.coupon_amount IS '??:settleList.couponAmount???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.recharge_card_amount IS '??:settleList.rechargeCardAmount???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.gift_card_amount IS '??:settleList.giftCardAmount???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepay_money IS '??:settleList.prepayMoney????/?????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consume_money IS '??:settleList.consumeMoney??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goods_money IS '??:settleList.goodsMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.real_goods_money IS '??:settleList.realGoodsMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.table_charge_money IS '??:settleList.tableChargeMoney??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.service_money IS '??:settleList.serviceMoney??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activity_discount IS '??:settleList.activityDiscount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.all_coupon_discount IS '??:settleList.allCouponDiscount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goods_promotion_money IS '??:settleList.goodsPromotionMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistant_promotion_money IS '??:settleList.assistantPromotionMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistant_pd_money IS '??:settleList.assistantPdMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistant_cx_money IS '??:settleList.assistantCxMoney????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistant_manual_discount IS '??:settleList.assistantManualDiscount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.coupon_sale_amount IS '??:settleList.couponSaleAmount??/???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.member_discount_amount IS '??:settleList.memberDiscountAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.point_discount_price IS '??:settleList.pointDiscountPrice????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.point_discount_cost IS '??:settleList.pointDiscountCost????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjust_amount IS '??:settleList.adjustAmount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rounding_amount IS '??:settleList.roundingAmount??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payment_method IS '??:settleList.paymentMethod????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.can_be_revoked IS '??:settleList.canBeRevoked???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.is_bind_member IS '??:settleList.isBindMember??????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.is_activity IS '??:settleList.isActivity????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.is_use_coupon IS '??:settleList.isUseCoupon?????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.is_use_discount IS '??:settleList.isUseDiscount????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operator_id IS '??:settleList.operatorId????/???ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operator_name_snapshot IS '??:settleList.operatorName?????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesman_user_id IS '??:settleList.salesManUserId??????ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesman_name IS '??:settleList.salesManName???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.order_remark IS '??:settleList.orderRemark??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.table_id IS '??:settleList.tableId????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serial_number IS '??:settleList.serialNumber???/?????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoke_order_id IS '??:settleList.revokeOrderId???????ID?';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoke_order_name IS '??:settleList.revokeOrderName???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoke_time IS '??:settleList.revokeTime??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.create_time IS '??:settleList.createTime????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pay_time IS '??:settleList.payTime??????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.site_profile IS '??:siteProfile????????JSON??';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '????????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '??????????/???';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '???????????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '??JSON?????? settleList ? siteProfile??';
+
+
+-- ========== 缁撹处璁板綍锛堢粨璐﹁褰?json -> data.settleList[] = {settleList, siteProfile}锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ settleList JSONB,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.settlement_records IS '鏉ユ簮锛氱粨璐﹁褰?json -> data.settleList锛涢棬搴楁秷璐圭粨绠楄褰曪紝settleList鍚噾棰濇槑缁嗐€乻ettleType銆佹敮浠樻柟寮忕瓑锛宻iteProfile涓洪棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.settlement_records.settleList IS '鏉ユ簮:data.settleList[].settleList锛涚粨绠椾富瀵硅薄鍘熸牱瀛樺偍銆?;
+COMMENT ON COLUMN billiards_ods.settlement_records.siteProfile IS '鏉ユ簮:data.settleList[].siteProfile锛涢棬搴椾俊鎭揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣锛堢粨璐﹁褰曪級銆?;
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '鍘熷JSON鏁存潯璁板綍锛堝惈settleList涓巗iteProfile锛夛紝渚夸簬澶嶅師銆?;
+
+-- ========== 鍔╂暀搴熼櫎锛堝姪鏁欏簾闄?json -> data.abolitionAssistants锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS '鏉ユ簮锛氬姪鏁欏簾闄?json -> data.abolitionAssistants锛涜褰曞姪鏁欒搴熼櫎/鍙栨秷鐨勫彴娆′笌閲戦銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '鏉ユ簮:data.abolitionAssistants.id锛涘簾闄よ褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '鏉ユ簮:data.abolitionAssistants.siteId锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '鏉ユ簮:data.abolitionAssistants.siteProfile锛涢棬搴椾俊鎭揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '鏉ユ簮:data.abolitionAssistants.assistantName锛涘姪鏁欏鍚?鏄电О銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '鏉ユ簮:data.abolitionAssistants.assistantAbolishAmount锛涜搴熼櫎鐨勮垂鐢ㄩ噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '鏉ユ簮:data.abolitionAssistants.assistantOn锛涘姪鏁欎笂閽熸爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '鏉ユ簮:data.abolitionAssistants.pdChargeMinutes锛涜璐瑰垎閽熸暟銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '鏉ユ簮:data.abolitionAssistants.tableAreaId锛涘彴鐞冨尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '鏉ユ簮:data.abolitionAssistants.tableArea锛涘彴鐞冨尯鍩熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '鏉ユ簮:data.abolitionAssistants.tableId锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '鏉ユ簮:data.abolitionAssistants.tableName锛涘彴妗屽悕绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '鏉ユ簮:data.abolitionAssistants.trashReason锛涘簾闄ゅ師鍥犮€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '鏉ユ簮:data.abolitionAssistants.createTime锛涜褰曟椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欏叾浠栧瓧娈点€?;
+
+-- ========== 鍔╂暀璐﹀彿锛堝姪鏁欒处鍙?json -> data.assistantInfos锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ gender INT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ get_grade_times INT,
+ video_introduction_url TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS '鏉ユ簮锛氬姪鏁欒处鍙?json -> data.assistantInfos锛涘姪鏁欎汉鍛樻。妗堬紝鍏抽敭瀛楁灞曞紑锛屽叾浣欎繚鎸佸湪payload銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '鏉ユ簮:data.assistantInfos.id锛涘姪鏁欎富閿€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '鏉ユ簮:data.assistantInfos.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '鏉ユ簮:data.assistantInfos.site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '鏉ユ簮:data.assistantInfos.assistant_no锛涘姪鏁欑紪鍙枫€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '鏉ユ簮:data.assistantInfos.nickname锛涘姪鏁欐樀绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '鏉ユ簮:data.assistantInfos.real_name锛涚湡瀹炲鍚嶃€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '鏉ユ簮:data.assistantInfos.mobile锛涙墜鏈哄彿銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '鏉ユ簮:data.assistantInfos.team_id锛涙墍灞炲洟闃烮D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '鏉ユ簮:data.assistantInfos.team_name锛涙墍灞炲洟闃熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '鏉ユ簮:data.assistantInfos.level锛涘姪鏁欑骇鍒€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '鏉ユ簮:data.assistantInfos.assistant_status锛涜处鍙风姸鎬?鍦ㄨ亴鐘舵€併€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '鏉ユ簮:data.assistantInfos.work_status锛涘伐浣滅姸鎬侊紙鍦ㄧ嚎/蹇欑绛夛級銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '鏉ユ簮:data.assistantInfos.leave_status锛涜鍋?绂诲矖鐘舵€併€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '鏉ユ簮:data.assistantInfos.entry_time锛涘叆鑱屾椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '鏉ユ簮:data.assistantInfos.resign_time锛涚鑱?鎾ゅ矖鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '鏉ユ簮:data.assistantInfos.start_time锛涜处鍙峰惎鐢ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '鏉ユ簮:data.assistantInfos.end_time锛涜处鍙风粨鏉熸椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '鏉ユ簮:data.assistantInfos.create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '鏉ユ簮:data.assistantInfos.update_time锛涙洿鏂版椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '鏉ユ簮:data.assistantInfos.order_trade_no锛涘叧鑱旇鍗曞彿锛堣嫢鏈夛級銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '鏉ユ簮:data.assistantInfos.staff_id锛涘憳宸D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '鏉ユ簮:data.assistantInfos.staff_profile_id锛涘憳宸ユ。妗圛D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '鏉ユ簮:data.assistantInfos.system_role_id锛涚郴缁熻鑹睮D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '鏉ユ簮:data.assistantInfos.avatar锛涘ご鍍忋€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '鏉ユ簮:data.assistantInfos.gender锛涙€у埆銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '鏉ユ簮:data.assistantInfos.show_status锛涙槸鍚﹀睍绀恒€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '鏉ユ簮:data.assistantInfos.show_sort锛涘睍绀烘帓搴忋€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '鏉ユ簮:data.assistantInfos.sum_grade锛涚患鍚堣瘎鍒嗙疮璁°€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '鏉ユ簮:data.assistantInfos.get_grade_times锛涜璇勫垎娆℃暟銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '鏉ユ簮:data.assistantInfos.video_introduction_url锛涗粙缁嶈棰慤RL銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '鍘熷JSON鏁存潯璁板綍锛屽寘鍚湭灞曞紑鐨勫叾瀹冨瓧娈碉紙allow_cx銆乧harge_way绛夛級銆?;
+
+-- ========== 鍔╂暀娴佹按锛堝姪鏁欐祦姘?json -> data.orderAssistantDetails锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ assistant_team_id_dup BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.assistant_service_records IS '鏉ユ簮锛氬姪鏁欐祦姘?json -> data.orderAssistantDetails锛涘姪鏁欐湇鍔¤璐规槑缁嗭紝涓昏瀛楁灞曞紑锛屽叾浣欎繚鐣欏湪payload銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '鏉ユ簮:data.orderAssistantDetails.id锛涘姪鏁欐祦姘翠富閿€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '鏉ユ簮:data.orderAssistantDetails.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '鏉ユ簮:data.orderAssistantDetails.site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '鏉ユ簮:data.orderAssistantDetails.siteProfile锛涢棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '鏉ユ簮:data.orderAssistantDetails.site_table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '鏉ユ簮:data.orderAssistantDetails.order_settle_id锛涚粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '鏉ユ簮:data.orderAssistantDetails.order_trade_no锛涜鍗曞彿銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '鏉ユ簮:data.orderAssistantDetails.order_pay_id锛涙敮浠樿褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '鏉ユ簮:data.orderAssistantDetails.order_assistant_id锛涘姪鏁欒鍗曞叧鑱擨D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '鏉ユ簮:data.orderAssistantDetails.order_assistant_type锛涘姪鏁欑被鍨嬫灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '鏉ユ簮:data.orderAssistantDetails.assistantName锛涘姪鏁欏悕绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '鏉ユ簮:data.orderAssistantDetails.assistantNo锛涘姪鏁欑紪鍙枫€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '鏉ユ簮:data.orderAssistantDetails.assistant_level锛涘姪鏁欑瓑绾с€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '鏉ユ簮:data.orderAssistantDetails.assistant_team_id锛涘姪鏁欏洟闃烮D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '鏉ユ簮:data.orderAssistantDetails.nickname锛涘姪鏁欐樀绉般€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '鏉ユ簮:data.orderAssistantDetails.ledger_name锛涜璐归」鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '鏉ユ簮:data.orderAssistantDetails.ledger_group_name锛涜璐瑰垎缁勩€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '鏉ユ簮:data.orderAssistantDetails.ledger_amount锛涜璐归噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '鏉ユ簮:data.orderAssistantDetails.ledger_count锛涜璐规暟閲?鏃堕暱銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '鏉ユ簮:data.orderAssistantDetails.ledger_unit_price锛涜璐瑰崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '鏉ユ簮:data.orderAssistantDetails.ledger_status锛涜璐圭姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '鏉ユ簮:data.orderAssistantDetails.ledger_start_time锛涜璐瑰紑濮嬫椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '鏉ユ簮:data.orderAssistantDetails.ledger_end_time锛涜璐圭粨鏉熸椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '鏉ユ簮:data.orderAssistantDetails.manual_discount_amount锛涗汉宸ヤ紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '鏉ユ簮:data.orderAssistantDetails.member_discount_amount锛涗細鍛樻姌鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '鏉ユ簮:data.orderAssistantDetails.coupon_deduct_money锛涘埜鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '鏉ユ簮:data.orderAssistantDetails.service_money锛涙湇鍔¤垂閲戦銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '鏉ユ簮:data.orderAssistantDetails.projected_income锛涢璁℃敹鍏ャ€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '鏉ユ簮:data.orderAssistantDetails.real_use_seconds锛涘疄闄呬娇鐢ㄧ鏁般€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '鏉ユ簮:data.orderAssistantDetails.income_seconds锛涜璐圭鏁般€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '鏉ユ簮:data.orderAssistantDetails.start_use_time锛涘紑濮嬩娇鐢ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '鏉ユ簮:data.orderAssistantDetails.last_use_time锛涙渶鍚庝娇鐢ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '鏉ユ簮:data.orderAssistantDetails.create_time锛涙祦姘村垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '鏉ユ簮:data.orderAssistantDetails.is_single_order锛涙槸鍚﹀崟鐐硅鍗曟爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '鏉ユ簮:data.orderAssistantDetails.is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '鏉ユ簮:data.orderAssistantDetails.is_trash锛涘簾闄ゆ爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '鏉ユ簮:data.orderAssistantDetails.trash_reason锛涘簾闄ゅ師鍥犮€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '鏉ユ簮:data.orderAssistantDetails.trash_applicant_id锛涘簾闄ょ敵璇蜂汉ID銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '鏉ユ簮:data.orderAssistantDetails.trash_applicant_name锛涘簾闄ょ敵璇蜂汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '鏉ユ簮:data.orderAssistantDetails.operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '鏉ユ簮:data.orderAssistantDetails.operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '鏉ユ簮:data.orderAssistantDetails.salesman_name锛涢攢鍞?鎺ュ緟濮撳悕銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '鏉ユ簮:data.orderAssistantDetails.salesman_org_id锛涢攢鍞粍缁嘔D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '鏉ユ簮:data.orderAssistantDetails.salesman_user_id锛涢攢鍞敤鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '鏉ユ簮:data.orderAssistantDetails.person_org_id锛涘憳宸ョ粍缁嘔D銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id_dup IS '鏉ユ簮:data.orderAssistantDetails.assistant_team_id锛涘洟闃烮D鍐椾綑灞曞紑銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '鏉ユ簮:data.orderAssistantDetails.add_clock锛涘姞閽熸椂闀挎爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '鏉ユ簮:data.orderAssistantDetails.returns_clock锛涢€€閽熸椂闀挎爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '鏉ユ簮:data.orderAssistantDetails.composite_grade锛涚患鍚堣瘎鍒嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '鏉ユ簮:data.orderAssistantDetails.composite_grade_time锛涜瘎鍒嗘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '鏉ユ簮:data.orderAssistantDetails.skill_grade锛涙妧鑳借瘎鍒嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '鏉ユ簮:data.orderAssistantDetails.service_grade锛涙湇鍔¤瘎鍒嗐€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '鏉ユ簮:data.orderAssistantDetails.sum_grade锛涜瘎鍒嗙疮璁°€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '鏉ユ簮:data.orderAssistantDetails.grade_status锛涜瘎鍒嗙姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '鏉ユ簮:data.orderAssistantDetails.get_grade_times锛涜璇勫垎娆℃暟銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '鏉ユ簮:data.orderAssistantDetails.is_not_responding锛涙槸鍚︽棤鍝嶅簲銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '鏉ユ簮:data.orderAssistantDetails.is_confirm锛涙槸鍚﹀凡纭銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '鍘熷JSON鏁存潯璁板綍锛屽叾浣欏瓧娈碉紙濡俵evelName銆乻killName绛夛級淇濈暀銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 鍙版鍒楄〃锛堝彴妗屽垪琛?json -> data.siteTables锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.site_tables_master IS '鏉ユ簮锛氬彴妗屽垪琛?json -> data.siteTables锛涢棬搴楀彴妗屽熀纭€淇℃伅銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '鏉ユ簮:data.siteTables.id锛涘彴妗屼富閿€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '鏉ユ簮:data.siteTables.site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '鏉ユ簮:data.siteTables.siteName锛涢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master."appletQrCodeUrl" IS '鏉ユ簮:data.siteTables.appletQrCodeUrl锛涘皬绋嬪簭浜岀淮鐮乁RL銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '鏉ユ簮:data.siteTables.areaName锛涘尯鍩熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '鏉ユ簮:data.siteTables.audit_status锛涘鏍哥姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '鏉ユ簮:data.siteTables.charge_free锛涙槸鍚﹀厤璐瑰彴銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '鏉ユ簮:data.siteTables.create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '鏉ユ簮:data.siteTables.delay_lights_time锛涘欢鏃跺叧鐏鏁般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '鏉ユ簮:data.siteTables.is_online_reservation锛涙槸鍚︽敮鎸佺嚎涓婇绾︺€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '鏉ユ簮:data.siteTables.is_rest_area锛涙槸鍚︿紤鎭尯銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '鏉ユ簮:data.siteTables.light_status锛涚伅鍏夌姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '鏉ユ簮:data.siteTables.only_allow_groupon锛涙槸鍚︿粎鍏佽鍥㈣喘銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '鏉ユ簮:data.siteTables.order_delay_time锛涘紑鍗曞欢鏃剁銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '鏉ユ簮:data.siteTables.self_table锛涙槸鍚﹁嚜鍔╁彴銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '鏉ユ簮:data.siteTables.show_status锛涘睍绀虹姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '鏉ユ簮:data.siteTables.site_table_area_id锛涘彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '鏉ユ簮:data.siteTables.tableStatusName锛涘彴妗岀姸鎬佸悕绉般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '鏉ユ簮:data.siteTables.table_cloth_use_Cycle锛涚悆鍙板竷浣跨敤鍛ㄦ湡銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '鏉ユ簮:data.siteTables.table_cloth_use_time锛涚悆鍙板竷鏈€杩戞洿鎹㈡椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '鏉ユ簮:data.siteTables.table_name锛涘彴妗屽悕绉般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '鏉ユ簮:data.siteTables.table_price锛涘彴璐瑰崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '鏉ユ簮:data.siteTables.table_status锛涘彴妗岀姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '鏉ユ簮:data.siteTables.temporary_light_second锛涗复鏃跺紑鐏鏁般€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '鏉ユ簮:data.siteTables.virtual_table锛涙槸鍚﹁櫄鎷熷彴銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欓澶栧瓧娈点€?;
+
+-- ========== 鍙拌垂鎵撴姌锛堝彴璐规墦鎶?json -> data.taiFeeAdjustInfos锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS '鏉ユ簮锛氬彴璐规墦鎶?json -> data.taiFeeAdjustInfos锛涘彴璐规姌鎵?璋冧环璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '鏉ユ簮:data.taiFeeAdjustInfos.id锛涙姌鎵h褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '鏉ユ簮:data.taiFeeAdjustInfos.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '鏉ユ簮:data.taiFeeAdjustInfos.site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '鏉ユ簮:data.taiFeeAdjustInfos.siteProfile锛涢棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '鏉ユ簮:data.taiFeeAdjustInfos.site_table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '鏉ユ簮:data.taiFeeAdjustInfos.tableProfile锛涘彴妗屼俊鎭揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '鏉ユ簮:data.taiFeeAdjustInfos.tenant_table_area_id锛涘彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '鏉ユ簮:data.taiFeeAdjustInfos.adjust_type锛涜皟浠风被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '鏉ユ簮:data.taiFeeAdjustInfos.ledger_amount锛涜皟浠峰悗閲戦銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '鏉ユ簮:data.taiFeeAdjustInfos.ledger_count锛涜皟浠锋暟閲?鏃堕暱銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '鏉ユ簮:data.taiFeeAdjustInfos.ledger_name锛涜璐归」鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '鏉ユ簮:data.taiFeeAdjustInfos.ledger_status锛涜璐圭姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '鏉ユ簮:data.taiFeeAdjustInfos.applicant_id锛涚敵璇蜂汉ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '鏉ユ簮:data.taiFeeAdjustInfos.applicant_name锛涚敵璇蜂汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '鏉ユ簮:data.taiFeeAdjustInfos.operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '鏉ユ簮:data.taiFeeAdjustInfos.operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '鏉ユ簮:data.taiFeeAdjustInfos.order_settle_id锛涘叧鑱旂粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '鏉ユ簮:data.taiFeeAdjustInfos.order_trade_no锛涜鍗曞彿銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '鏉ユ簮:data.taiFeeAdjustInfos.is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '鏉ユ簮:data.taiFeeAdjustInfos.create_time锛涜褰曞垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欏叾浠栧瓧娈点€?;
+
+-- ========== 鍙拌垂娴佹按锛堝彴璐规祦姘?json -> data.siteTableUseDetailsList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS '鏉ユ簮锛氬彴璐规祦姘?json -> data.siteTableUseDetailsList锛涘彴妗屼娇鐢ㄨ璐规祦姘淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '鏉ユ簮:data.siteTableUseDetailsList.id锛涘彴璐规祦姘翠富閿€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '鏉ユ簮:data.siteTableUseDetailsList.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '鏉ユ簮:data.siteTableUseDetailsList.site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '鏉ユ簮:data.siteTableUseDetailsList.siteProfile锛涢棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '鏉ユ簮:data.siteTableUseDetailsList.site_table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '鏉ユ簮:data.siteTableUseDetailsList.site_table_area_id锛涘彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '鏉ユ簮:data.siteTableUseDetailsList.site_table_area_name锛涘彴妗屽尯鍩熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '鏉ユ簮:data.siteTableUseDetailsList.tenant_table_area_id锛涚鎴蜂晶鍙版鍖哄煙ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '鏉ユ簮:data.siteTableUseDetailsList.order_trade_no锛涜鍗曞彿銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '鏉ユ簮:data.siteTableUseDetailsList.order_pay_id锛涙敮浠樿褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '鏉ユ簮:data.siteTableUseDetailsList.order_settle_id锛涚粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_name锛涜璐归」鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_amount锛涜璐归噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_count锛涜璐规暟閲?鏃堕暱銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_unit_price锛涜璐瑰崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_status锛涜璐圭姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_start_time锛涜璐瑰紑濮嬫椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '鏉ユ簮:data.siteTableUseDetailsList.ledger_end_time锛涜璐圭粨鏉熸椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '鏉ユ簮:data.siteTableUseDetailsList.start_use_time锛涘紑濮嬩娇鐢ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '鏉ユ簮:data.siteTableUseDetailsList.last_use_time锛涙渶鍚庝娇鐢ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '鏉ユ簮:data.siteTableUseDetailsList.real_table_use_seconds锛涘疄闄呬娇鐢ㄧ銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '鏉ユ簮:data.siteTableUseDetailsList.real_table_charge_money锛涘疄闄呭彴璐归噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '鏉ユ簮:data.siteTableUseDetailsList.add_clock_seconds锛涘姞閽熺鏁般€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '鏉ユ簮:data.siteTableUseDetailsList.adjust_amount锛涜皟鏁撮噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '鏉ユ簮:data.siteTableUseDetailsList.coupon_promotion_amount锛涗紭鎯犲埜浼樻儬閲戦銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '鏉ユ簮:data.siteTableUseDetailsList.member_discount_amount锛涗細鍛樻姌鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '鏉ユ簮:data.siteTableUseDetailsList.used_card_amount锛涘崱鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '鏉ユ簮:data.siteTableUseDetailsList.mgmt_fee锛涚鐞嗚垂銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '鏉ユ簮:data.siteTableUseDetailsList.service_money锛涙湇鍔¤垂銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '鏉ユ簮:data.siteTableUseDetailsList.fee_total锛涘悎璁″彴璐广€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '鏉ユ簮:data.siteTableUseDetailsList.is_single_order锛涙槸鍚﹀崟鐐硅鍗曘€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '鏉ユ簮:data.siteTableUseDetailsList.is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '鏉ユ簮:data.siteTableUseDetailsList.member_id锛涗細鍛業D锛堣嫢缁戝畾锛夈€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '鏉ユ簮:data.siteTableUseDetailsList.operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '鏉ユ簮:data.siteTableUseDetailsList.operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '鏉ユ簮:data.siteTableUseDetailsList.salesman_name锛涢攢鍞?鎺ュ緟濮撳悕銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '鏉ユ簮:data.siteTableUseDetailsList.salesman_org_id锛涢攢鍞粍缁嘔D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '鏉ユ簮:data.siteTableUseDetailsList.salesman_user_id锛涢攢鍞敤鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '鏉ユ簮:data.siteTableUseDetailsList.create_time锛涜褰曞垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 搴撳瓨鍙樺寲璁板綍1锛堝簱瀛樺彉鍖栬褰?.json -> data.queryDeliveryRecordsList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS '鏉ユ簮锛氬簱瀛樺彉鍖栬褰?.json -> data.queryDeliveryRecordsList锛涘簱瀛樺彉鍔ㄦ祦姘达紙鍚富鍓崟浣嶏級銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '鏉ユ簮:data.queryDeliveryRecordsList.siteGoodsStockId锛涘簱瀛樺彉鍔ㄨ褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '鏉ユ簮:data.queryDeliveryRecordsList.tenantId锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '鏉ユ簮:data.queryDeliveryRecordsList.siteId锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '鏉ユ簮:data.queryDeliveryRecordsList.siteGoodsId锛涢棬搴楀晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '鏉ユ簮:data.queryDeliveryRecordsList.goodsName锛涘晢鍝佸悕绉般€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '鏉ユ簮:data.queryDeliveryRecordsList.goodsCategoryId锛涗竴绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '鏉ユ簮:data.queryDeliveryRecordsList.goodsSecondCategoryId锛涗簩绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '鏉ユ簮:data.queryDeliveryRecordsList.unit锛涜閲忓崟浣嶃€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '鏉ユ簮:data.queryDeliveryRecordsList.price锛涘崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '鏉ユ簮:data.queryDeliveryRecordsList.stockType锛涘彉鍔ㄧ被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '鏉ユ簮:data.queryDeliveryRecordsList.changeNum锛涗富鍗曚綅鍙樺姩鏁伴噺銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '鏉ユ簮:data.queryDeliveryRecordsList.startNum锛涘彉鍔ㄥ墠搴撳瓨锛堜富鍗曚綅锛夈€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '鏉ユ簮:data.queryDeliveryRecordsList.endNum锛涘彉鍔ㄥ悗搴撳瓨锛堜富鍗曚綅锛夈€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '鏉ユ簮:data.queryDeliveryRecordsList.changeNumA锛涘壇鍗曚綅鍙樺姩鏁伴噺銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '鏉ユ簮:data.queryDeliveryRecordsList.startNumA锛涘彉鍔ㄥ墠搴撳瓨锛堝壇鍗曚綅锛夈€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '鏉ユ簮:data.queryDeliveryRecordsList.endNumA锛涘彉鍔ㄥ悗搴撳瓨锛堝壇鍗曚綅锛夈€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '鏉ユ簮:data.queryDeliveryRecordsList.remark锛涘娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '鏉ユ簮:data.queryDeliveryRecordsList.operatorName锛涙搷浣滀汉銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '鏉ユ簮:data.queryDeliveryRecordsList.createTime锛涘彉鍔ㄦ椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 搴撳瓨鍙樺寲璁板綍2锛堝簱瀛樺彉鍖栬褰?.json -> data.goodsCategoryList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS '鏉ユ簮锛氬簱瀛樺彉鍖栬褰?.json -> data.goodsCategoryList锛涢棬搴楀晢鍝佸垎绫伙紙鍚瓙绫籧ategoryBoxes锛夈€?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '鏉ユ簮:data.goodsCategoryList.id锛涘垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '鏉ユ簮:data.goodsCategoryList.tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '鏉ユ簮:data.goodsCategoryList.category_name锛涘垎绫诲悕绉般€?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '鏉ユ簮:data.goodsCategoryList.alias_name锛涘埆鍚嶃€?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '鏉ユ簮:data.goodsCategoryList.pid锛涚埗绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '鏉ユ簮:data.goodsCategoryList.business_name锛涗笟鍔$嚎鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '鏉ユ簮:data.goodsCategoryList.tenant_goods_business_id锛涗笟鍔$嚎ID銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '鏉ユ簮:data.goodsCategoryList.open_salesman锛涢攢鍞紑鍏?鏉冮檺銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '鏉ユ簮:data.goodsCategoryList.categoryBoxes锛涘瓙鍒嗙被鍒楄〃JSON銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '鏉ユ簮:data.goodsCategoryList.sort锛涙帓搴忓彿銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '鏉ユ簮:data.goodsCategoryList.is_warehousing锛涙槸鍚﹀叆搴撶鐞嗐€?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 搴撳瓨姹囨€伙紙搴撳瓨姹囨€?json锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS '鏉ユ簮锛氬簱瀛樻眹鎬?json锛涢棬搴楀晢鍝佸湪缁熻鍖洪棿鍐呯殑搴撳瓨姹囨€汇€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '鏉ユ簮:siteGoodsId锛涢棬搴楀晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '鏉ユ簮:goodsName锛涘晢鍝佸悕绉般€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '鏉ユ簮:goodsUnit锛涜閲忓崟浣嶃€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '鏉ユ簮:goodsCategoryId锛涗竴绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '鏉ユ簮:goodsCategorySecondId锛涗簩绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '鏉ユ簮:categoryName锛涘垎绫诲悕绉般€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '鏉ユ簮:rangeStartStock锛涘尯闂存湡鍒濆簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '鏉ユ簮:rangeEndStock锛涘尯闂存湡鏈簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '鏉ユ簮:rangeIn锛涘尯闂村叆搴撴暟閲忋€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '鏉ユ簮:rangeOut锛涘尯闂村嚭搴撴暟閲忋€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '鏉ユ簮:rangeSale锛涘尯闂撮攢鍞暟閲忋€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '鏉ユ簮:rangeSaleMoney锛涘尯闂撮攢鍞噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '鏉ユ簮:rangeInventory锛涚洏鐐瑰樊寮傛暟閲忋€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '鏉ユ簮:currentStock锛涘綋鍓嶅簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 鏀粯璁板綍锛堟敮浠樿褰?json锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.payment_transactions IS '鏉ユ簮锛氭敮浠樿褰?json锛涙敮浠樻祦姘达紝鍚嚎涓?绾夸笅娓犻亾銆?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '鏉ユ簮:id锛涙敮浠樿褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '鏉ユ簮:siteProfile锛涢棬搴椾俊鎭揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '鏉ユ簮:relate_type锛涘叧鑱斾笟鍔$被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '鏉ユ簮:relate_id锛涘叧鑱斾笟鍔D銆?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '鏉ユ簮:pay_amount锛涙敮浠橀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '鏉ユ簮:pay_status锛涙敮浠樼姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '鏉ユ簮:pay_time锛涙敮浠樻椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '鏉ユ簮:payment_method锛涙敮浠樻柟寮忔灇涓俱€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '鏉ユ簮:online_pay_channel锛涚嚎涓婃笭閬撲唬鐮併€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 閫€娆捐褰曪紙閫€娆捐褰?json锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.refund_transactions IS '鏉ユ簮锛氶€€娆捐褰?json锛涢€€娆惧強鍐荤粨璧勯噾鏄庣粏銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '鏉ユ簮:id锛涢€€娆捐褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '鏉ユ簮:tenantName锛涚鎴峰悕绉般€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '鏉ユ簮:siteProfile锛涢棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '鏉ユ簮:relate_type锛涘叧鑱斾笟鍔$被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '鏉ユ簮:relate_id锛涘叧鑱斾笟鍔D銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '鏉ユ簮:pay_sn锛涙敮浠樻祦姘村彿銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '鏉ユ簮:pay_amount锛涘師鏀粯閲戦銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '鏉ユ簮:refund_amount锛涢€€娆鹃噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '鏉ユ簮:round_amount锛涙姽闆堕噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '鏉ユ簮:pay_status锛涚姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '鏉ユ簮:pay_time锛涙敮浠?閫€娆炬椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '鏉ユ簮:payment_method锛涙敮浠樻柟寮忋€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '鏉ユ簮:pay_terminal锛涙敮浠樼粓绔被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '鏉ユ簮:pay_config_id锛涙敮浠橀厤缃甀D銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '鏉ユ簮:online_pay_channel锛涚嚎涓婃笭閬撱€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '鏉ユ簮:online_pay_type锛涚嚎涓婃敮浠樼被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '鏉ユ簮:channel_fee锛涙笭閬撴墜缁垂銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '鏉ユ簮:channel_payer_id锛涙笭閬撲粯娆句汉鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '鏉ユ簮:channel_pay_no锛涙笭閬撴敮浠樺崟鍙枫€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '鏉ユ簮:member_id锛涗細鍛業D銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '鏉ユ簮:member_card_id锛涗細鍛樺崱ID銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '鏉ユ簮:cashier_point_id锛涙敹閾剁偣ID銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '鏉ユ簮:operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '鏉ユ簮:action_type锛涘姩浣滅被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '鏉ユ簮:check_status锛涘鏍哥姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '鏉ユ簮:is_revoke锛涙槸鍚︽挙閿€銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '鏉ユ簮:balance_frozen_amount锛涗綑棰濆喕缁撻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '鏉ユ簮:card_frozen_amount锛涘崱鍐荤粨閲戦銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 骞冲彴楠屽埜璁板綍锛堝钩鍙伴獙鍒歌褰?json锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS '鏉ユ簮锛氬钩鍙伴獙鍒歌褰?json锛涚涓夋柟/骞冲彴鍒告牳閿€娴佹按銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '鏉ユ簮:id锛涙祦姘翠富閿€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '鏉ユ簮:verify_id锛涢獙鍒窱D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '鏉ユ簮:certificate_id锛涘埜鍑瘉ID銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '鏉ユ簮:coupon_code锛涘埜鐮併€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '鏉ユ簮:coupon_name锛涘埜鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '鏉ユ簮:coupon_channel锛涘埜娓犻亾銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '鏉ユ簮:groupon_type锛涘洟璐被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '鏉ユ簮:group_package_id锛涘洟璐椁怚D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '鏉ユ簮:sale_price锛涘敭鍗栦环銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '鏉ユ簮:coupon_money锛涘埜闈㈤/鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '鏉ユ簮:coupon_free_time锛涜禒閫佹椂闀?鍏嶈垂鏃堕暱銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '鏉ユ簮:coupon_cover锛涘埜灏侀潰URL銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '鏉ユ簮:coupon_remark锛涘埜澶囨敞銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '鏉ユ簮:use_status锛涙牳閿€鐘舵€併€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '鏉ユ簮:consume_time锛涙牳閿€鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '鏉ユ簮:deal_id锛涗氦鏄揑D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '鏉ユ簮:channel_deal_id锛涙笭閬撲氦鏄揑D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '鏉ユ簮:site_order_id锛涢棬搴楄鍗旾D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '鏉ユ簮:table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '鏉ユ簮:operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '鏉ユ簮:operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '鏉ユ簮:siteProfile锛涢棬搴楀揩鐓с€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 鍟嗗搧妗f锛堝晢鍝佹。妗?json -> data.tenantGoodsList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS '鏉ユ簮锛氬晢鍝佹。妗?json -> data.tenantGoodsList锛涚鎴峰晢鍝佷富鏁版嵁銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '鏉ユ簮:id锛涘晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '鏉ユ簮:goods_name锛涘晢鍝佸悕绉般€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '鏉ユ簮:goods_bar_code锛涙潯鐮併€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '鏉ユ簮:goods_category_id锛涗竴绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '鏉ユ簮:goods_second_category_id锛涗簩绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '鏉ユ簮:categoryName锛涘垎绫诲悕绉般€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '鏉ユ簮:unit锛涜閲忓崟浣嶃€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '鏉ユ簮:goods_number锛涘晢鍝佺紪鐮併€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '鏉ユ簮:goods_state锛涘晢鍝佺姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '鏉ユ簮:sale_channel锛涢攢鍞笭閬撱€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '鏉ユ簮:able_discount锛涙槸鍚﹀彲鎶樻墸銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '鏉ユ簮:able_site_transfer锛涙槸鍚﹀彲璺ㄥ簵銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '鏉ユ簮:is_warehousing锛涙槸鍚︾撼鍏ュ簱瀛樼鐞嗐€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '鏉ユ簮:isInSite锛涙槸鍚﹂棬搴楀晢鍝佹爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '鏉ユ簮:cost_price锛涙垚鏈环銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '鏉ユ簮:cost_price_type锛涙垚鏈环绫诲瀷銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '鏉ユ簮:market_price锛涘競鍦轰环銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '鏉ユ簮:min_discount_price锛涙渶浣庢姌鍚庝环銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '鏉ユ簮:common_sale_royalty锛涙櫘閫氶攢鍞彁鎴愩€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '鏉ユ簮:point_sale_royalty锛涚Н鍒嗛攢鍞彁鎴愩€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '鏉ユ簮:pinyin_initial锛涙嫾闊抽瀛楁瘝銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '鏉ユ簮:commodityCode锛涘晢鍝佺紪鐮侊紙瀛楁鍒悕锛夈€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '鏉ユ簮:commodity_code锛涘晢鍝佺紪鐮侊紙鍙︿竴瀛楁锛夈€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '鏉ユ簮:goods_cover锛涘晢鍝佸浘鐗囥€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '鏉ユ簮:supplier_id锛涗緵搴斿晢ID銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '鏉ユ簮:remark_name锛涘娉ㄥ悕銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '鏉ユ簮:update_time锛涙洿鏂版椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '鍘熷JSON鏁存潯璁板綍锛屼繚鐣欐湭灞曞紑瀛楁銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 鍥㈣喘濂楅锛堝洟璐椁?json -> data.packageCouponList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '鏉ユ簮锛氬洟璐椁?json -> data.packageCouponList锛涘洟璐?濂楅瀹氫箟銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '鏉ユ簮:id锛涘椁愯褰曚富閿€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '鏉ユ簮:package_id锛涘椁怚D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '鏉ユ簮:package_name锛涘椁愬悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '鏉ユ簮:selling_price锛涘敭鍗栦环銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '鏉ユ簮:coupon_money锛涘埜闈㈤/浠峰€笺€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '鏉ユ簮:date_type锛涙棩鏈熺被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '鏉ユ簮:date_info锛涙棩鏈熼檺鍒舵弿杩般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '鏉ユ簮:start_time锛涙湁鏁堟湡寮€濮嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '鏉ユ簮:end_time锛涙湁鏁堟湡缁撴潫銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '鏉ユ簮:start_clock锛涙瘡鏃ュ彲鐢ㄥ紑濮嬫椂娈点€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '鏉ユ簮:end_clock锛涙瘡鏃ュ彲鐢ㄧ粨鏉熸椂娈点€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '鏉ユ簮:add_start_clock锛涢檮鍔犲紑濮嬫椂娈点€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '鏉ユ簮:add_end_clock锛涢檮鍔犵粨鏉熸椂娈点€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '鏉ユ簮:duration锛涘彲鐢ㄦ椂闀?鍒嗛挓銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '鏉ユ簮:usable_count锛涘彲鐢ㄦ鏁般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '鏉ユ簮:usable_range锛涘彲鐢ㄨ寖鍥寸被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '鏉ユ簮:table_area_id锛涘彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '鏉ユ簮:table_area_name锛涘彴妗屽尯鍩熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '鏉ユ簮:table_area_id_list锛涘彲鐢ㄥ彴妗屽尯鍩熷垪琛↗SON銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '鏉ユ簮:tenant_table_area_id锛涚鎴峰彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '鏉ユ簮:tenant_table_area_id_list锛涚鎴峰彴妗屽尯鍩熷垪琛↗SON銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '鏉ユ簮:site_name锛涢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '鏉ユ簮:card_type_ids锛涘厑璁镐娇鐢ㄧ殑鍗$被鍨婭D鍒楄〃JSON銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '鏉ユ簮:group_type锛涘洟璐被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '鏉ユ簮:system_group_type锛涚郴缁熷洟璐被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '鏉ユ簮:type锛涘椁愮被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '鏉ユ簮:effective_status锛涚敓鏁堢姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '鏉ユ簮:is_enabled锛涘惎鐢ㄦ爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '鏉ユ簮:max_selectable_categories锛涘彲閫夊垎绫讳笂闄愩€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '鏉ユ簮:area_tag_type锛涘尯鍩熸爣绛剧被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '鏉ユ簮:creator_name锛涘垱寤轰汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+
+-- ========== 鍥㈣喘濂楅娴佹按锛堝洟璐椁愭祦姘?json -> data.siteTableUseDetailsList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages_ledger (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.group_buy_packages_ledger IS '鏉ユ簮锛氬洟璐椁愭祦姘?json -> data.siteTableUseDetailsList锛涘洟璐埜浣跨敤/鏍搁攢娴佹按銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.id IS '鏉ユ簮:id锛涙祦姘翠富閿€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.siteName IS '鏉ユ簮:siteName锛涢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.table_id IS '鏉ユ簮:table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.tableName IS '鏉ユ簮:tableName锛涘彴妗屽悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.tableAreaName IS '鏉ユ簮:tableAreaName锛涘彴妗屽尯鍩熷悕绉般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.tenant_table_area_id IS '鏉ユ簮:tenant_table_area_id锛涚鎴峰彴妗屽尯鍩烮D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.order_trade_no IS '鏉ユ簮:order_trade_no锛涜鍗曞彿銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.order_settle_id IS '鏉ユ簮:order_settle_id锛涚粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.order_pay_id IS '鏉ユ簮:order_pay_id锛涙敮浠樿褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.order_coupon_id IS '鏉ユ簮:order_coupon_id锛涜鍗曞埜ID銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.order_coupon_channel IS '鏉ユ簮:order_coupon_channel锛涘埜娓犻亾銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.coupon_code IS '鏉ユ簮:coupon_code锛涘埜鐮併€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.coupon_money IS '鏉ユ簮:coupon_money锛涘埜閲戦銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.coupon_origin_id IS '鏉ユ簮:coupon_origin_id锛涘埜鏉ユ簮ID銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_name IS '鏉ユ簮:ledger_name锛涜璐归」鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_group_name IS '鏉ユ簮:ledger_group_name锛涜璐瑰垎缁勩€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_amount IS '鏉ユ簮:ledger_amount锛涢噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_count IS '鏉ユ簮:ledger_count锛涙暟閲?鏃堕暱銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_unit_price IS '鏉ユ簮:ledger_unit_price锛涘崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.ledger_status IS '鏉ユ簮:ledger_status锛涚姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.table_charge_seconds IS '鏉ユ簮:table_charge_seconds锛涘彴璐硅璐圭鏁般€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.promotion_activity_id IS '鏉ユ簮:promotion_activity_id锛涗績閿€娲诲姩ID銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.promotion_coupon_id IS '鏉ユ簮:promotion_coupon_id锛涗績閿€鍒窱D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.promotion_seconds IS '鏉ユ簮:promotion_seconds锛涗績閿€璧犻€佹椂闀裤€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.offer_type IS '鏉ユ簮:offer_type锛涗紭鎯犵被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.assistant_promotion_money IS '鏉ユ簮:assistant_promotion_money锛涘姪鏁欎紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.assistant_service_promotion_money IS '鏉ユ簮:assistant_service_promotion_money锛涘姪鏁欐湇鍔′紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.table_service_promotion_money IS '鏉ユ簮:table_service_promotion_money锛涘彴璐逛紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.goods_promotion_money IS '鏉ユ簮:goods_promotion_money锛涘晢鍝佷紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.recharge_promotion_money IS '鏉ユ簮:recharge_promotion_money锛涘厖鍊间紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.reward_promotion_money IS '鏉ユ簮:reward_promotion_money锛涘鍔变紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.goodsOptionPrice IS '鏉ユ簮:goodsOptionPrice锛涘晢鍝佽鏍间环銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.salesman_name IS '鏉ユ簮:salesman_name锛涢攢鍞鍚嶃€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.sales_man_org_id IS '鏉ユ簮:sales_man_org_id锛涢攢鍞粍缁嘔D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.salesman_role_id IS '鏉ユ簮:salesman_role_id锛涢攢鍞鑹睮D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.salesman_user_id IS '鏉ユ簮:salesman_user_id锛涢攢鍞敤鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.operator_id IS '鏉ユ簮:operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.operator_name IS '鏉ユ簮:operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.is_single_order IS '鏉ユ簮:is_single_order锛涙槸鍚﹀崟鐐硅鍗曘€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎鏍囪瘑銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_ledger.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 灏忕エ璇︽儏锛堝皬绁ㄨ鎯?json -> data.data锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS '鏉ユ簮锛氬皬绁ㄨ鎯?json -> data.data锛涘皬绁?缁撶畻璇﹀崟锛屾槑缁嗕笌浼氬憳蹇収瀛楯SON銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '鏉ユ簮:orderSettleId锛涚粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '鏉ユ簮:actualPayment锛涘疄鏀堕噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '鏉ユ簮:adjustAmount锛涙姽闆?璋冩暣閲戦銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '鏉ユ簮:assistantManualDiscount锛涘姪鏁欎汉宸ヤ紭鎯犮€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '鏉ユ簮:balanceAmount锛涗綑棰濇敮浠橀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '鏉ユ簮:cashierName锛涙敹閾跺憳銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '鏉ユ簮:consumeMoney锛涙秷璐归噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '鏉ユ簮:couponAmount锛涘埜鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '鏉ユ簮:deliveryAddress锛涢厤閫佸湴鍧€銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '鏉ユ簮:deliveryFee锛涢厤閫佽垂銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '鏉ユ簮:ledgerAmount锛涜处鍗曢噾棰濇眹鎬汇€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '鏉ユ簮:memberDeductAmount锛涗細鍛樻姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '鏉ユ簮:memberOfferAmount锛涗細鍛樹紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '鏉ユ簮:onlineReturnAmount锛涚嚎涓婇€€杩橀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '鏉ユ簮:orderRemark锛涜鍗曞娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '鏉ユ簮:orderSettleNumber锛涚粨绠楀崟鍙枫€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '鏉ユ簮:payMemberBalance锛涗細鍛樹綑棰濇敮浠橀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '鏉ユ簮:payTime锛涙敮浠樻椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '鏉ユ簮:paymentMethod锛涙敮浠樻柟寮忋€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '鏉ユ簮:pointDiscountCost锛涚Н鍒嗘姷鎵f垚鏈€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '鏉ユ簮:pointDiscountPrice锛涚Н鍒嗘姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '鏉ユ簮:prepayMoney锛涢浠橀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '鏉ユ簮:refundAmount锛涢€€娆鹃噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '鏉ユ簮:returnGoodsAmount锛涢€€璐ч噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '鏉ユ簮:rewardName锛涘鍔辫鏄庛€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '鏉ユ簮:settleType锛涚粨绠楃被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '鏉ユ簮:siteAddress锛涢棬搴楀湴鍧€銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '鏉ユ簮:siteBusinessTel锛涢棬搴楃數璇濄€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '鏉ユ簮:siteId锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '鏉ユ簮:siteName锛涢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '鏉ユ簮:tenantId锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '鏉ユ簮:tenantName锛涚鎴峰悕绉般€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '鏉ユ簮:ticketCustomContent锛涜嚜瀹氫箟绁ㄩ潰鍐呭銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '鏉ユ簮:ticketRemark锛涘皬绁ㄥ娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '鏉ユ簮:voucherMoney锛涗唬閲戝埜閲戦銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '鏉ユ簮:memberProfile锛涗細鍛樺揩鐓SON銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '鏉ユ簮:orderItem锛涘晢鍝?鍙版/鍒稿垎椤规槑缁咼SON銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '鏉ユ簮:tenantMemberCardLogs锛涘叧鑱斾綑棰濆彉鏇存祦姘碕SON銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 闂ㄥ簵鍟嗗搧妗f锛堥棬搴楀晢鍝佹。妗?.json -> data.orderGoodsList锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.store_goods_master IS '鏉ユ簮锛氶棬搴楀晢鍝佹。妗?.json -> data.orderGoodsList锛涢棬搴楀眰鍟嗗搧妗f锛屽叧閿簱瀛?浠锋牸瀛楁灞曞紑銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '鏉ユ簮:id锛涢棬搴楀晢鍝佽褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '鏉ユ簮:siteName锛涢棬搴楀悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '鏉ユ簮:tenant_goods_id锛涚鎴峰晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '鏉ユ簮:goods_name锛涘晢鍝佸悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '鏉ユ簮:goods_bar_code锛涙潯鐮併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '鏉ユ簮:goods_category_id锛涗竴绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '鏉ユ簮:goods_second_category_id锛涗簩绾у垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '鏉ユ簮:oneCategoryName锛涗竴绾у垎绫诲悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '鏉ユ簮:twoCategoryName锛涗簩绾у垎绫诲悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '鏉ユ簮:unit锛涜閲忓崟浣嶃€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '鏉ユ簮:sale_price锛涢攢鍞环銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '鏉ユ簮:cost_price锛涙垚鏈环銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '鏉ユ簮:cost_price_type锛涙垚鏈环绫诲瀷銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '鏉ユ簮:min_discount_price锛涙渶浣庢姌鎵d环銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '鏉ユ簮:safe_stock锛涘畨鍏ㄥ簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '鏉ユ簮:stock锛涘綋鍓嶅簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '鏉ユ簮:stock_A锛涜緟鍗曚綅搴撳瓨銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '鏉ユ簮:sale_num锛涚疮璁¢攢閲忋€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '鏉ユ簮:total_purchase_cost锛涚疮璁¢噰璐垚鏈€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '鏉ユ簮:total_sales锛涚疮璁¢攢鍞銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '鏉ユ簮:average_monthly_sales锛涙湀鍧囬攢閲忋€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '鏉ユ簮:enable_status锛涘惎鐢ㄧ姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '鏉ユ簮:audit_status锛涘鏍哥姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '鏉ユ簮:goods_state锛涘晢鍝佺姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '鏉ユ簮:is_warehousing锛涙槸鍚︾撼鍏ュ簱瀛樸€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '鏉ユ簮:able_discount锛涘彲鍚︽姌鎵c€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '鏉ユ簮:able_site_transfer锛涘彲鍚﹁法搴楄皟鎷ㄣ€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '鏉ユ簮:forbid_sell_status锛涚鍞姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master."freeze" IS '鏉ユ簮:freeze锛涘喕缁撴爣璁般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '鏉ユ簮:send_state锛涢厤閫佺姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '鏉ユ簮:custom_label_type锛涜嚜瀹氫箟鏍囩绫诲瀷銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '鏉ユ簮:option_required锛涜鏍煎繀閫夋爣璇嗐€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '鏉ユ簮:sale_channel锛涢攢鍞笭閬撱€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '鏉ユ簮:remark锛涘娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '鏉ユ簮:pinyin_initial锛涙嫾闊抽瀛楁瘝銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '鏉ユ簮:goods_cover锛涘晢鍝佸浘鐗囥€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '鏉ユ簮:update_time锛涙洿鏂版椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
+-- ========== 闂ㄥ簵鍟嗗搧閿€鍞褰曪紙闂ㄥ簵鍟嗗搧閿€鍞褰?json -> data.orderGoodsLedgers锛?==========
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS '鏉ユ簮锛氶棬搴楀晢鍝侀攢鍞褰?json -> data.orderGoodsLedgers锛涘晢鍝侀攢鍞槑缁嗐€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '鏉ユ簮:id锛涢攢鍞槑缁咺D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '鏉ユ簮:tenant_id锛涚鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '鏉ユ簮:site_id锛涢棬搴桰D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '鏉ユ簮:site_goods_id锛涢棬搴楀晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '鏉ユ簮:tenant_goods_id锛涚鎴峰晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '鏉ユ簮:order_settle_id锛涚粨绠楀崟ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '鏉ユ簮:order_trade_no锛涜鍗曞彿銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '鏉ユ簮:order_goods_id锛涜鍗曞晢鍝両D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '鏉ユ簮:order_pay_id锛涙敮浠樿褰旾D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '鏉ユ簮:order_coupon_id锛涜鍗曞埜ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '鏉ユ簮:ledger_name锛涜璐归」鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '鏉ユ簮:ledger_group_name锛涜璐瑰垎缁勩€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '鏉ユ簮:ledger_amount锛涢噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '鏉ユ簮:ledger_count锛涙暟閲忋€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '鏉ユ簮:ledger_unit_price锛涘崟浠枫€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '鏉ユ簮:ledger_status锛涚姸鎬併€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '鏉ユ簮:discount_money锛涙姌鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '鏉ユ簮:coupon_deduct_money锛涘埜鎶垫墸閲戦銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '鏉ユ簮:member_discount_amount锛涗細鍛樹紭鎯犻噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '鏉ユ簮:option_coupon_deduct_money锛涜鏍煎眰绾у埜鎶垫墸銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '鏉ユ簮:option_member_discount_money锛涜鏍煎眰绾т細鍛樹紭鎯犮€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '鏉ユ簮:point_discount_money锛涚Н鍒嗘姷鎵i噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '鏉ユ簮:point_discount_money_cost锛涚Н鍒嗘姷鎵f垚鏈€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '鏉ユ簮:real_goods_money锛涘疄浠樺晢鍝侀噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '鏉ユ簮:cost_money锛涙垚鏈噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '鏉ユ簮:push_money锛涙彁鎴愰噾棰濄€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '鏉ユ簮:sales_type锛涢攢鍞被鍨嬨€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '鏉ユ簮:is_single_order锛涙槸鍚﹀崟鐐硅鍗曘€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '鏉ユ簮:is_delete锛涢€昏緫鍒犻櫎銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '鏉ユ簮:goods_remark锛涘晢鍝佸娉ㄣ€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '鏉ユ簮:option_price锛涜鏍煎姞浠枫€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '鏉ユ簮:option_value_name锛涜鏍煎€煎悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '鏉ユ簮:option_name锛涜鏍煎悕绉般€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '鏉ユ簮:member_coupon_id锛涗細鍛樺埜ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '鏉ユ簮:package_coupon_id锛涘椁愬埜ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '鏉ユ簮:sales_man_org_id锛涢攢鍞粍缁嘔D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '鏉ユ簮:salesman_name锛涢攢鍞鍚嶃€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '鏉ユ簮:salesman_role_id锛涢攢鍞鑹睮D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '鏉ユ簮:salesman_user_id锛涢攢鍞敤鎴稩D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '鏉ユ簮:operator_id锛涙搷浣滀汉ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '鏉ユ簮:operator_name锛涙搷浣滀汉鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '鏉ユ簮:openSalesman锛涘紑鍗曞憳鍚嶇О銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '鏉ユ簮:site_table_id锛涘彴妗孖D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '鏉ユ簮:tenant_goods_business_id锛涗笟鍔$嚎ID銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '鏉ユ簮:tenant_goods_category_id锛涚鎴峰垎绫籌D銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '鏉ユ簮:create_time锛涘垱寤烘椂闂淬€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '鍘熷JSON鏁存潯璁板綍銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰勩€?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣銆?;
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿銆?;
+
diff --git a/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql.bak_20251209 b/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql.bak_20251209
new file mode 100644
index 0000000..d8a0408
--- /dev/null
+++ b/tmp/etl_billiards_misc/backups/schema_ODS_doc.sql.bak_20251209
@@ -0,0 +1,1886 @@
+-- 文件:schema_ODS_doc.sql
+-- 说明:ODS 层 DDL,表名与示例 JSON 前缀对应,用于本地回放/调试。
+-- 编码:UTF-8
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS '对应JSON字段:member_profiles.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_profiles-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '对应JSON字段:tenant_id,说明::,示例值及对应分析:租户/品牌 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '对应JSON字段:register_site_id,说明::,示例值及对应分析:会员的注册门店 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '对应JSON字段:site_name,说明::,示例值及对应分析:注册门店名称,属于冗余字段,用于直接展示。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '对应JSON字段:id,说明::,示例值及对应分析:这是“租户内会员账户”的主键 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '对应JSON字段:system_member_id,说明:(结合其它文件):,示例值及对应分析:这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明:类型:int,示例值及对应分析:唯一值个数:4';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '对应JSON字段:member_card_grade_name,说明::,示例值及对应分析:这是“会员卡种类/等级”的定义字段。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '对应JSON字段:mobile,说明::,示例值及对应分析:会员绑定的手机号码。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '对应JSON字段:nickname,说明::,示例值及对应分析:会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '对应JSON字段:point,说明::,示例值及对应分析:当前积分余额(这条会员账户的积分值)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '对应JSON字段:growth_value,说明:(按常见会员体系设计):,示例值及对应分析:成长值 / 经验值,用于会员等级晋升的累计指标。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '对应JSON字段:referrer_member_id,说明:(按命名推断):,示例值及对应分析:推荐人会员 ID,用于记录该会员是由哪位老会员推荐。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '对应JSON字段:status,说明:(按命名推断):,示例值及对应分析:帐户状态(偏“卡状态/档案状态”)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '对应JSON字段:user_status,说明:(结合行业惯例):,示例值及对应分析:用户账号状态(偏“用户逻辑”层面的状态)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '对应JSON字段:create_time,说明::,示例值及对应分析:会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '对应JSON字段:member_balance_changes.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '对应JSON字段:tenant_id,说明::租户/商户 ID,本数据中是固定值(同一品牌/商户)。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '对应JSON字段:site_id,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '对应JSON字段:register_site_id,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '对应JSON字段:registerSiteName,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '对应JSON字段:paySiteName,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '对应JSON字段:id,说明::余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::商户维度的会员 ID(租户内会员主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '对应JSON字段:tenant_member_card_id,说明::会员卡账户 ID,在租户内唯一标识某张卡。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '对应JSON字段:system_member_id,说明::系统级(全局)会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '对应JSON字段:memberName,说明::会员姓名或称呼(非昵称字段)。,示例值及对应分析:说明:例如“陈腾鑫”“胡先生”“江先生”等,多为中文姓名或带“先生”称呼。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '对应JSON字段:memberMobile,说明::会员手机号。,示例值及对应分析:说明:字符型存储,完整手机号,用来识别会员与联系客户。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '对应JSON字段:card_type_id,说明::卡种类型 ID,用于区分不同卡种。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '对应JSON字段:memberCardTypeName,说明::卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '对应JSON字段:account_data,说明::本次变动的金额(元),正数表示增加,负数表示减少。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '对应JSON字段:before,说明::本次变动前,该卡账户的余额(元)。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '对应JSON字段:after,说明::本次变动后,该卡账户的余额(元)。,示例值及对应分析:重要关系:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):与退款业务相关的金额字段,但在当前这份导出中实际未使用:,示例值及对应分析:可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '对应JSON字段:from_type,说明:(根据金额符号与 remark 综合推断):,示例值及对应分析:1:日常消费扣款';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '对应JSON字段:payment_method,说明:类型:int,枚举,示例值及对应分析:值分布:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '对应JSON字段:relate_id,说明:(推测):关联业务记录的 ID:,示例值及对应分析:例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '对应JSON字段:remark,说明::,示例值及对应分析:当为空时,说明这条变动没有额外备注说明。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '对应JSON字段:operator_id,说明::执行此次余额变更操作的员工 ID。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。,示例值及对应分析:9. 状态字段与标志';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标记:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '对应JSON字段:create_time,说明::本条余额变更记录的创建时间,通常接近交易发生时间。,示例值及对应分析:说明:可与订单、支付记录的时间做对齐,构造时序链路(但你现在不要求做时序分析,这里只说明结构)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '对应JSON字段:member_stored_value_cards.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,与其他 JSON 中 tenant_id 一致。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::当前商户(品牌/租户)中会员的主键 ID。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '对应JSON字段:system_member_id,说明::系统级会员 ID(跨门店统一主键)。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '对应JSON字段:register_site_id,说明::卡首次办理的门店 ID。,示例值及对应分析:对应门店的 site_id;本数据中所有卡都是在同一家门店开卡。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '对应JSON字段:site_name,说明::卡归属门店名称(视图中的展示字段)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '对应JSON字段:id,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明::卡等级/卡类代码,和下面两个名称字段一一对应。,示例值及对应分析:枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '对应JSON字段:member_card_grade_code_name,说明::卡等级/卡类名称。,示例值及对应分析:枚举值(与上面 code 一一对应):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '对应JSON字段:member_card_type_name,说明::卡类型名称,实际与 member_card_grade_code_name 一致。,示例值及对应分析:枚举值同上。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '对应JSON字段:member_name,说明::持卡会员姓名快照。,示例值及对应分析:特点:存在 null(20 张卡没有绑定会员名字)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '对应JSON字段:member_mobile,说明::持卡会员手机号快照。,示例值及对应分析:特点:与 member_name 对应,多数有值,少量为 null。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '对应JSON字段:card_type_id,说明::卡种 ID(定义“这是哪一种卡”)。,示例值及对应分析:枚举(按数据分布):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '对应JSON字段:card_no,说明:(推测):实体卡物理卡号/条码号。当前这批卡看起来全部为“无物理卡号”(可能是全部虚拟卡或卡号隐藏不导出)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '对应JSON字段:card_physics_type,说明::物理卡类型。,示例值及对应分析:当前数据:全部为 1。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '对应JSON字段:balance,说明::当前卡内余额(主要针对储值卡、部分券卡)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '对应JSON字段:denomination,说明:(推测):面额/初始储值额度。,示例值及对应分析:本页数据未填充此字段;可能在分类型卡(如次卡/券)中才有意义,或者另有配置表。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '对应JSON字段:table_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '对应JSON字段:goods_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '对应JSON字段:assistant_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '对应JSON字段:assistant_reward_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '对应JSON字段:table_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '对应JSON字段:assistant_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '对应JSON字段:coupon_discount,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '对应JSON字段:goods_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '对应JSON字段:assistant_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '对应JSON字段:table_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '对应JSON字段:goods_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '对应JSON字段:assistant_reward_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '对应JSON字段:table_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '对应JSON字段:assistant_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '对应JSON字段:goods_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '对应JSON字段:assistant_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '对应JSON字段:table_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '对应JSON字段:goods_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '对应JSON字段:coupon_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '对应JSON字段:assistant_reward_deduct_radio,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '对应JSON字段:tableCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '对应JSON字段:tableServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '对应JSON字段:goodsCarDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '对应JSON字段:goodsServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '对应JSON字段:assistantCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '对应JSON字段:assistantServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '对应JSON字段:assistantRewardCardDeduct,说明::助教奖励金方向扣款的配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '对应JSON字段:cardSettleDeduct,说明:已在扣卡规则部分说明,当前为 0。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '对应JSON字段:couponCardDeduct,说明::与卡绑定的“券额度扣除配置”。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '对应JSON字段:deliveryFeeDeduct,说明::配送费可否/多少从卡中抵扣,目前无业务发生。,示例值及对应分析:综合来看:本门店的卡片在“规则配置层”预留了大量细粒度控制字段,但目前实际使用只体现在“balance”和“可用范围”,折扣和具体扣卡规则基本都未启用(全部保持默认值 10 折、100%比例、0 扣款),真正扣款逻辑在交易流水中体现。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '对应JSON字段:use_scene,说明::卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。,示例值及对应分析:2. 会员信息与关联字段';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '对应JSON字段:able_cross_site,说明::是否允许跨店使用。,示例值及对应分析:1:可以跨门店使用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '对应JSON字段:is_allow_give,说明::是否允许转赠/转让给其他会员。,示例值及对应分析:0:不允许;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '对应JSON字段:is_allow_order_deduct,说明::是否允许在“订单层面统一扣款”。,示例值及对应分析:0:不允许(仅按项目扣卡);';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '对应JSON字段:bind_password,说明::卡绑定密码,用于消费或查询验证(目前未启用)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '对应JSON字段:goods_discount_range_type,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '对应JSON字段:tableAreaId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '对应JSON字段:effect_site_id,说明:(推测):卡片限定生效门店 ID。,示例值及对应分析:为 0 时,配合 able_cross_site=1,可解释为“所有门店可用”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '对应JSON字段:start_time,说明::卡片生效开始时间(有效期起始)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '对应JSON字段:end_time,说明::卡片有效期结束时间。,示例值及对应分析:start_time / end_time 组合就是卡的有效期。不同卡种有效期配置不同,如储值卡长效、月卡固定一个月等。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '对应JSON字段:disable_start_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '对应JSON字段:disable_end_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '对应JSON字段:last_consume_time,说明::最近一次消费时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '对应JSON字段:create_time,说明::卡片创建时间(开卡时间)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '对应JSON字段:status,说明:(推测):,示例值及对应分析:1:正常可用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '对应JSON字段:sort,说明::在前端展示或某些列表中的排序权重。,示例值及对应分析:具体取值分布不重要,主要反映展示优先级。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '对应JSON字段:tenantAvatar,说明::品牌头像 URL(未配置)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '对应JSON字段:tenantName,说明::租户/品牌名称(当前导出为空)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '对应JSON字段:pdAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '对应JSON字段:cxAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS '对应JSON字段:recharge_settlements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '对应JSON字段:id,说明::本条充值结算记录的主键 ID(唯一标识一条充值/撤销记录)。,示例值及对应分析:唯一性:74 条记录全部不同。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '对应JSON字段:tenantid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '对应JSON字段:siteid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '对应JSON字段:sitename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '对应JSON字段:balanceamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '对应JSON字段:cardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '对应JSON字段:cashamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '对应JSON字段:couponamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '对应JSON字段:createtime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '对应JSON字段:memberid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '对应JSON字段:membername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '对应JSON字段:memberphone,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '对应JSON字段:tableid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '对应JSON字段:consumemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '对应JSON字段:onlineamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '对应JSON字段:operatorid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '对应JSON字段:operatorname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '对应JSON字段:revokeordername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '对应JSON字段:revoketime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '对应JSON字段:payamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '对应JSON字段:pointamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '对应JSON字段:refundamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '对应JSON字段:settlename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '对应JSON字段:settlestatus,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '对应JSON字段:settletype,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '对应JSON字段:paytime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '对应JSON字段:roundingamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '对应JSON字段:adjustamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '对应JSON字段:servicemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '对应JSON字段:salesmanname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '对应JSON字段:orderremark,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '对应JSON字段:canberevoked,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '对应JSON字段:serialnumber,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '对应JSON字段:isusediscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '对应JSON字段:isactivity,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '对应JSON字段:isbindmember,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '对应JSON字段:isfirst,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS '对应JSON字段:settlement_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '对应JSON字段:id,说明::结账记录主键 ID(订单结算 ID)。,示例值及对应分析:结构关联:';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '对应JSON字段:tenantid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '对应JSON字段:siteid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '对应JSON字段:sitename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '对应JSON字段:balanceamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '对应JSON字段:cardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '对应JSON字段:cashamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '对应JSON字段:couponamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '对应JSON字段:createtime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '对应JSON字段:memberid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '对应JSON字段:membername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '对应JSON字段:memberphone,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '对应JSON字段:tableid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '对应JSON字段:consumemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '对应JSON字段:onlineamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '对应JSON字段:operatorid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '对应JSON字段:operatorname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '对应JSON字段:revokeordername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '对应JSON字段:revoketime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '对应JSON字段:payamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '对应JSON字段:pointamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '对应JSON字段:refundamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '对应JSON字段:settlename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '对应JSON字段:settlestatus,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '对应JSON字段:settletype,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '对应JSON字段:paytime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '对应JSON字段:roundingamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '对应JSON字段:adjustamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '对应JSON字段:servicemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '对应JSON字段:salesmanname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '对应JSON字段:orderremark,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '对应JSON字段:canberevoked,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '对应JSON字段:serialnumber,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '对应JSON字段:isusediscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '对应JSON字段:isactivity,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '对应JSON字段:isbindmember,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '对应JSON字段:isfirst,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS '对应JSON字段:assistant_cancellation_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '对应JSON字段:id,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '对应JSON字段:siteId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '对应JSON字段:assistantName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '对应JSON字段:assistantAbolishAmount,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '对应JSON字段:assistantOn,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '对应JSON字段:pdChargeMinutes,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '对应JSON字段:tableAreaId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '对应JSON字段:tableArea,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '对应JSON字段:tableId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '对应JSON字段:tableName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '对应JSON字段:trashReason,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '对应JSON字段:createTime,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS '对应JSON字段:assistant_accounts_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '对应JSON字段:id,说明::助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。,示例值及对应分析:作用:所有与助教相关的事实表(助教流水、助教排班等)都会通过这个 ID 关联到该维表。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '对应JSON字段:tenant_id,说明::品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。,示例值及对应分析:用途:多门店时用来区分不同商户。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '对应JSON字段:site_id,说明::门店 ID,对应本次数据的这家球房(朗朗桌球)。,示例值及对应分析:关联:与其它 JSON(台费流水、库存、销售等)中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '对应JSON字段:assistant_no,说明:(结合字段名推测):助教工号 / 编号,便于业务侧识别。,示例值及对应分析:关联:在“助教流水.json”中有 assistantNo,与此字段对应。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '对应JSON字段:nickname,说明::助教在前台展示的昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:用途:与真实姓名区分,用于顾客侧展示。如在助教流水中 nickname 就是这个值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '对应JSON字段:real_name,说明::助教真实姓名,如“何海婷”“梁婷婷”等。,示例值及对应分析:关联:在“助教流水.json”的 assistantName 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '对应JSON字段:mobile,说明::助教手机号,用于登录绑定、通知、钉钉同步等。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '对应JSON字段:team_id,说明::助教所属团队 ID。,示例值及对应分析:关联:在“助教流水.json”中 assistant_team_id 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '对应JSON字段:team_name,说明::团队名称,展示用,和 team_id 一一对应。,示例值及对应分析:group_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '对应JSON字段:level,说明:(结合“助教流水中的 assistant_level / levelName 推测”):,示例值及对应分析:8:助教管理/管理员(和流水里的 "助教管理" 对应)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '对应JSON字段:assistant_status,说明:(推测):账号启用状态:,示例值及对应分析:1:启用';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '对应JSON字段:work_status,说明::,示例值及对应分析:1:在岗/可排班';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '对应JSON字段:leave_status,说明:类型:int,枚举。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '对应JSON字段:entry_time,说明::入职时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '对应JSON字段:resign_time,说明::离职日期;使用“远未来日期”作为“未离职”的占位。,示例值及对应分析:entry_type';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '对应JSON字段:start_time,说明:(推测):当前配置生效的开始日期。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '对应JSON字段:end_time,说明::当前配置生效的结束日期(例如一个周期性的排班/合同周期)。,示例值及对应分析:last_table_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '对应JSON字段:create_time,说明::账号创建时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '对应JSON字段:update_time,说明::账号最近一次被修改的时间(例如修改等级、昵称等)。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '对应JSON字段:order_trade_no,说明:(推测):该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。,示例值及对应分析:9. 灯控、钉钉等系统集成相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '对应JSON字段:staff_id,说明:(推测):预留给“人事系统员工 ID”的字段,目前未接入或未启用。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '对应JSON字段:staff_profile_id,说明:(推测):人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。,示例值及对应分析:4. 等级、计费与薪资配置字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '对应JSON字段:system_role_id,说明:?????? assistant_accounts_master-Analysis.md,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '对应JSON字段:avatar,说明::助教头像地址。,示例值及对应分析:introduce';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '对应JSON字段:gender,说明:(结合常见约定与值分布推测):,示例值及对应分析:0:未填/保密';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '对应JSON字段:show_status,说明:(推测):前台展示状态:,示例值及对应分析:1:在助教选择界面展示。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '对应JSON字段:show_sort,说明::前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。,示例值及对应分析:online_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '对应JSON字段:sum_grade,说明::评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '对应JSON字段:get_grade_times,说明::累计被评分次数。,示例值及对应分析:charge_way';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '对应JSON字段:video_introduction_url,说明::助教个人视频介绍地址。,示例值及对应分析:height';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '对应JSON字段:user_id,说明:账号对应的用户 ID/员工 ID,用于跨表关联。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '对应JSON字段:height,说明:身高(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '对应JSON字段:weight,说明:体重(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '对应JSON字段:job_num,说明:工号/岗位编号,保留原始取值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '对应JSON字段:assistant_grade,说明:平均评分,通常 = sum_grade/get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '对应JSON字段:introduce,说明:个人简介/自我介绍,可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '对应JSON字段:group_id,说明:分组/自定义分组 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '对应JSON字段:group_name,说明:分组名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '对应JSON字段:shop_name,说明:门店名称冗余。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '对应JSON字段:charge_way,说明:收费方式枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '对应JSON字段:entry_type,说明:入职类型枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '对应JSON字段:allow_cx,说明:是否允许超休/冲销(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '对应JSON字段:is_guaranteed,说明:是否保底(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '对应JSON字段:salary_grant_enabled,说明:薪资发放/补贴开关,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '对应JSON字段:light_status,说明:灯控状态/模式,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '对应JSON字段:online_status,说明:在线状态标记(0/1等)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '对应JSON字段:is_delete,说明:逻辑删除标记(0=有效,1=删除)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '对应JSON字段:cx_unit_price,说明:超休单价/冲销单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '对应JSON字段:pd_unit_price,说明:排钟/点钟单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '对应JSON字段:last_table_id,说明:最近服务桌台 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '对应JSON字段:last_table_name,说明:最近服务桌台名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '对应JSON字段:person_org_id,说明:人员组织 ID/部门 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '对应JSON字段:serial_number,说明:序列号/排序号,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '对应JSON字段:is_team_leader,说明:是否组长(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '对应JSON字段:criticism_status,说明:处罚/警告状态标记,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '对应JSON字段:ding_talk_synced,说明:是否已同步钉钉(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '对应JSON字段:site_light_cfg_id,说明:门店灯控配置 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '对应JSON字段:light_equipment_id,说明:灯控设备 ID/硬件编号。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '对应JSON字段:entry_sign_status,说明:入职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '对应JSON字段:resign_sign_status,说明:离职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS '对应JSON字段:assistant_service_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '对应JSON字段:id,说明::本条助教流水记录的主键 ID(流水唯一标识)。,示例值及对应分析:作用:在系统内部唯一定位这一条助教服务记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID;你这份数据中是固定值(同一个商户)。,示例值及对应分析:关联:全库所有表都有,作为“商户维度”的过滤键。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本数据中指“朗朗桌球”这一家门店。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。,示例值及对应分析:作用:冗余门店信息,方便查看(而不是每次都联表看门店档案)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::订单结算 ID,相当于“结账单号”的内部主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,整个订单层面的编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '对应JSON字段:order_pay_id,说明::关联到“支付记录”的主键 ID。,示例值及对应分析:作用:可以和支付记录中的 id / relate_id 等字段对应,找到这条助教服务对应的支付流水。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '对应JSON字段:order_assistant_id,说明::订单中“助教项目明细”的内部 ID。,示例值及对应分析:作用:如果订单里有多条助教项目(比如换助教、多个时间段),此字段唯一标识这一条助教明细。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '对应JSON字段:order_assistant_type,说明:(推测):,示例值及对应分析:1:常规助教服务(主课/基础课)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '对应JSON字段:assistantName,说明::助教姓名,如“何海婷”“胡敏”等。,示例值及对应分析:备注:和助教账号档案里的 real_name 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '对应JSON字段:assistantNo,说明::助教编号,例如 "27"。,示例值及对应分析:关联:在助教账号表里也有 assistant_no 字段,对应工号/编号。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '对应JSON字段:assistant_level,说明::助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。,示例值及对应分析:备注:属于展示用的冗余字段。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '对应JSON字段:assistant_team_id,说明::当前这条助教服务所对应的“课程/技能名称”。,示例值及对应分析:当 order_assistant_type = 1 时,多为“基础课”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '对应JSON字段:nickname,说明::助教对外昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:说明:从数据看,这个 nickname 是“助教昵称”,不是顾客昵称(容易混淆)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '对应JSON字段:ledger_name,说明:?????? assistant_service_records-Analysis.md,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。,示例值及对应分析:目前未被实际使用。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。,示例值及对应分析:说明:从数据看,这个金额对应“按原价计费”的金额,未扣除各种优惠。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计时总秒数。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::助教服务 标准单价(通常是标价:每小时、每节课的单价)。,示例值及对应分析:特点:如 98.0、108.0、190.0 等。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):助教流水记录状态:,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账层面记录的开始时间。,示例值及对应分析:说明:与 start_use_time 在当前数据中完全一致,可以视为“计费起始时间”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账层面的结束时间。,示例值及对应分析:说明:与 last_use_time 一致,可以视为“计费结束时间”。对于 real_use_seconds = 0 的记录,开始和结束时间相同,说明只是预约/录入,并未实际服务。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '对应JSON字段:manual_discount_amount,说明::收银员手动给予的减免金额(人工改价)。,示例值及对应分析:当前导出时间段内暂未出现手动打折的情况。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员卡折扣产生的优惠金额。,示例值及对应分析:说明:尽管字段里是 0,但实际折扣可能已经体现在 projected_income 与 ledger_amount 的差额中,这里只是未单独拆出。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '对应JSON字段:service_money,说明:(推测):用于记录与助教结算的金额(平台预留的“成本/分成”字段)。,示例值及对应分析:当前数据中未启用这个机制,所以全为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '对应JSON字段:projected_income,说明::实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。,示例值及对应分析:从数据:projected_income 明显低于 ledger_amount,说明中间有折扣,但折扣的明细并不全由下面几个字段体现(很多是卡权益内生折扣)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '对应JSON字段:real_use_seconds,说明::实际使用时长(秒)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '对应JSON字段:income_seconds,说明::计费秒数 / 应计收入对应的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '对应JSON字段:start_use_time,说明::助教实际开始服务时间。,示例值及对应分析:特点:正常情况下与 ledger_start_time 相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '对应JSON字段:last_use_time,说明::最后一次使用(实际服务)时间。,示例值及对应分析:特点:正常结束时与 ledger_end_time 相同;如果服务还未真正开始或立即结束,开始/结束时间可能相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '对应JSON字段:create_time,说明::这条助教流水记录创建时间(一般接近结算/下单时间)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独订单:,示例值及对应分析:1:本助教服务作为单独订单结算(或单独拆项)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '对应JSON字段:is_trash,说明::是否已废除/作废:,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '对应JSON字段:trash_reason,说明::废除原因(文本说明),例如“顾客取消”“录入错误”等。,示例值及对应分析:当前数据为空字符串,说明当前导出时间段没有被废除的助教流水记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '对应JSON字段:trash_applicant_id,说明::提出废除申请的员工 ID(通常是操作员/管理员)。,示例值及对应分析:当前数据全为 0,因此短期内没有发生废除操作。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '对应JSON字段:trash_applicant_name,说明::废除申请人姓名。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入/结算这条助教服务的员工)。,示例值及对应分析:关联:可与员工/账号表对应(本次导出未单独给员工表,但其他 JSON 里多处出现该 ID)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,与 operator_id 一起使用,便于直接阅读。,示例值及对应分析:user_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '对应JSON字段:salesman_name,说明::关联的“营业员/销售员姓名”,用于提成归属。,示例值及对应分析:观测:本数据中多数为空字符串,说明助教流水没有配置单独的营业员。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:观测:多为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID。,示例值及对应分析:观测:多为 0,代表未指定。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '对应JSON字段:person_org_id,说明:同样在上文说明:助教所属人事组织 ID。,示例值及对应分析:9. 作废 / 废除相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '对应JSON字段:add_clock,说明:(推测):加钟秒数,即在原有预约/服务基础上临时追加的时长。,示例值及对应分析:说明:值均为 60 的倍数(分钟级加钟),如 600 秒=10 分钟。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '对应JSON字段:returns_clock,说明:(推测):退钟秒数(取消加钟或提前结束退回的时间)。,示例值及对应分析:当前数据里没有退钟场景,所以全为 0,但字段设计已经预留。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '对应JSON字段:composite_grade,说明::综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '对应JSON字段:composite_grade_time,说明:(推测):最近一次评价时间/综合评分更新时间。现在都是默认“无效时间”。,示例值及对应分析:3. 桌台 / 门店维度字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '对应JSON字段:skill_grade,说明:(推测):顾客对“技能表现”的评分(整数或打分等级)。,示例值及对应分析:当前数据中还未产生评分记录,所以都是默认值 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '对应JSON字段:service_grade,说明:(推测):顾客对“服务态度”的评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '对应JSON字段:sum_grade,说明::累计评分总和(可能用于计算平均分),当前为 0。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '对应JSON字段:grade_status,说明:(推测):评价状态,比如:,示例值及对应分析:1 = 未评价/正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '对应JSON字段:get_grade_times,说明::该条记录对应的评价次数(或该助教被评价次数快照)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '对应JSON字段:is_not_responding,说明:(推测):是否存在“爽约/未响应”情况:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '对应JSON字段:is_confirm,说明:(推测):确认状态,例如:,示例值及对应分析:1:待确认;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS '对应JSON字段:site_tables_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '对应JSON字段:id,说明::台桌主键 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '对应JSON字段:siteName,说明::门店名称快照,冗余字段,配合 site_id 使用。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master."appletQrCodeUrl" IS '对应JSON字段:appletQrCodeUrl,说明::小程序二维码 URL。 一般用于:,示例值及对应分析:打印二维码贴在台上,顾客扫码可呼叫服务、查看账单或发起线上预约;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '对应JSON字段:areaName,说明::区域名称,用于前台展示和区域维度管理。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '对应JSON字段:audit_status,说明:(结合命名惯例):,示例值及对应分析:2:已审核/已启用;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '对应JSON字段:charge_free,说明:(推测):,示例值及对应分析:0:正常计费;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '对应JSON字段:create_time,说明::台桌配置的创建时间或最近一次创建/复制时间。,示例值及对应分析:三、与其它 JSON 的字段级关联关系(结构视角)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '对应JSON字段:delay_lights_time,说明:(推测):台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。,示例值及对应分析:本门店未启用延迟关灯功能(全部为 0)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '对应JSON字段:is_online_reservation,说明:(结合值分布推断):,示例值及对应分析:1:允许线上预约(可在小程序/线上平台预约这张台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '对应JSON字段:is_rest_area,说明:(推测):,示例值及对应分析:0:正常计费区域;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '对应JSON字段:light_status,说明:(结合命名推断):,示例值及对应分析:该字段是台灯/灯光状态开关位:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '对应JSON字段:only_allow_groupon,说明:(结合命名推断):,示例值及对应分析:1:仅允许团购/券预约使用(团购专用台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '对应JSON字段:order_delay_time,说明:(推测):订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。,示例值及对应分析:本门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '对应JSON字段:self_table,说明:(推测):,示例值及对应分析:1:“本门店自有台”,非共享或外部配置;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '对应JSON字段:show_status,说明:(推测):,示例值及对应分析:1:正常在前台“开台列表”中展示;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店维度的“台桌区域 ID”。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '对应JSON字段:tableStatusName,说明::table_status 的中文名称,仅为展示用途。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '对应JSON字段:table_cloth_use_Cycle,说明:(推测):,示例值及对应分析:台呢使用周期阈值,例如达到某个秒数后提醒更换;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '对应JSON字段:table_cloth_use_time,说明:(结合命名和数值特征):,示例值及对应分析:台呢使用累计时长,单位极大概率为“秒”:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '对应JSON字段:table_name,说明::台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '对应JSON字段:table_price,说明:(结构角度):,示例值及对应分析:设计上应为“台的基础单价”字段(例如按小时或按局单价);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '对应JSON字段:table_status,说明::台当前运行状态,真实反映某一时刻台的占用/暂停情况。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '对应JSON字段:temporary_light_second,说明:(推测):临时点灯时长(秒),例如手动临时开灯一段时间。,示例值及对应分析:本门店未使用。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '对应JSON字段:virtual_table,说明:(推测):,示例值及对应分析:0:物理台(实体存在的桌);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS '对应JSON字段:table_fee_discount_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '对应JSON字段:id,说明::台费打折 / 调整流水主键 ID。,示例值及对应分析:作用:在“台费调账表”中唯一标识一条折扣/调账操作。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:标识记录属于哪一个商户(同一个“非球科技”租户)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本批数据全部为同一家门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,用于报表时直接读取,无需再联门店档案。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '对应JSON字段:site_table_id,说明::台桌 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '对应JSON字段:tableProfile,说明::折扣发生时,对应台桌的配置信息快照。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的“台桌区域 ID”。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '对应JSON字段:adjust_type,说明:(根据文件含义 + 命名 + 数据):,示例值及对应分析:文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '对应JSON字段:ledger_amount,说明:(关键点):,示例值及对应分析:通过与 台费流水.json 做对比,可以明确:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '对应JSON字段:ledger_count,说明::,示例值及对应分析:这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '对应JSON字段:ledger_name,说明:(推测):,示例值及对应分析:设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '对应JSON字段:ledger_status,说明::,示例值及对应分析:1:生效调整(当前有效的台费打折 / 调账记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '对应JSON字段:applicant_id,说明::打折/调账申请人 ID。,示例值及对应分析:作用:记录谁发起了这次台费调整。 本时段内所有调整均由同一位员工发起。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '对应JSON字段:applicant_name,说明::申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '对应JSON字段:operator_id,说明::实际执行调账操作的操作员 ID。,示例值及对应分析:说明:这段时间内,“申请人”和“操作员”是同一个人。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单/小票 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '对应JSON字段:create_time,说明::台费调整记录的创建时间,即打折操作被执行的时间戳。,示例值及对应分析:说明:与台费流水中的 create_time(结算时间)相互配合,可以还原调整发生于结账之前还是之后。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS '对应JSON字段:table_fee_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '对应JSON字段:id,说明::台费流水记录主键(事实表主键)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。本文件所有记录都属于同一租户。,示例值及对应分析:关联:与所有其它 JSON 中的 tenant_id 一致,用于跨表做“商户维度”的过滤。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID,本次数据全部来自同一门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::当前门店的完整档案快照,冗余到流水表中,便于报表直接读取而无需再联表门店档案。,示例值及对应分析:三、与其它 JSON 的结构关联关系(从字段层面)';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店内“台桌区域” ID(站在门店物理布局的角度)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '对应JSON字段:site_table_area_name,说明::台桌区域的名称,用于门店表现和区域统计。,示例值及对应分析:4. 会员维度与相关字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的台桌区域 ID(品牌层面的同一类区域)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,是整笔订单的主编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '对应JSON字段:order_pay_id,说明::订单支付记录 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单号/结账 ID,对应一次结账操作。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '对应JSON字段:ledger_name,说明::台号名称,实际展示给员工/顾客看的桌台编号。,示例值及对应分析:备注:与 site_table_id 一一对应,是桌台维表中的名称字段冗余到流水里的快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '对应JSON字段:ledger_amount,说明::按单价与计费时长计算出的原始应收台费金额。,示例值及对应分析:近似关系:ledger_amount ≈ ledger_unit_price × ledger_count / 3600,考虑到四舍五入会有小数差。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计费秒数,计费用秒数(应收时长)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::台费结算时设置的 每小时单价/计费单价。,示例值及对应分析:用途:与 ledger_count 共同决定原始应收额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):,示例值及对应分析:1:正常已结算台费;';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账上的计费起始时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账上的计费结束时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '对应JSON字段:start_use_time,说明::台开始使用的时间(实际开台时间)。,示例值及对应分析:特点:在数据中,与 ledger_start_time 完全相同(见下)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '对应JSON字段:last_use_time,说明::最后使用/操作时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '对应JSON字段:real_table_use_seconds,说明::实际使用的总秒数(系统真实统计的使用时长)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '对应JSON字段:real_table_charge_money,说明::台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '对应JSON字段:add_clock_seconds,说明::加钟秒数,在原有使用基础上追加的时长。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '对应JSON字段:adjust_amount,说明::调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '对应JSON字段:coupon_promotion_amount,说明::由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。,示例值及对应分析:特点:当 real_table_charge_money = 0 且该字段为 ledger_amount 时,说明整笔台费是由券促销全额承担。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '对应JSON字段:member_discount_amount,说明:上文已说明,这里补充与金额的结构关系:,示例值及对应分析:功能:表示由会员折扣或会员权益承担的那部分金额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '对应JSON字段:used_card_amount,说明::由储值卡、次卡等“卡内余额”抵扣的金额。,示例值及对应分析:说明:字段设计已预留,但本段时间内台费没有通过储值卡扣款,或者卡扣款在其他表体现。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '对应JSON字段:mgmt_fee,说明:(推测):管理费字段,用于未来支持“台费附加管理费/服务费”的功能。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '对应JSON字段:service_money,说明:(推测):门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。,示例值及对应分析:说明:当前门店未启用此字段结算台费。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '对应JSON字段:fee_total,说明::各种附加费用(如管理费、服务费)合计值。,示例值及对应分析:说明:和 mgmt_fee 一样,目前作为预留字段,没有实际使用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):,示例值及对应分析:1:该台费记录对应的是一个独立计费单元(单独结算的桌费);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '对应JSON字段:member_id,说明::门店/租户内的会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID,负责开台/结账的员工账号 ID。,示例值及对应分析:关联:与员工/账号体系中的用户 ID 对应(与助教账号的 user_id 属于同一种 ID 体系)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '对应JSON字段:salesman_name,说明::业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。,示例值及对应分析:当前门店未启用该字段做提成归属。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属机构/部门 ID。,示例值及对应分析:8. 状态 / 标记类字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员的用户 ID(与 salesman_name 搭配)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '对应JSON字段:create_time,说明::这条台费流水记录的创建时间,通常接近结账时间。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS '对应JSON字段:goods_stock_movements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '对应JSON字段:siteGoodsStockId,说明::门店某个“商品库存记录”的主键 ID。,示例值及对应分析:特点:每条库存变动记录对应一个 siteGoodsStockId,同一个商品可能在不同库存记录中出现(例如不同仓位或不同批次)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '对应JSON字段:tenantId,说明::租户/品牌 ID。,示例值及对应分析:观测:全部记录相同值,说明属于同一商户。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:观测:本文件中所有记录的 siteId 都相同,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '对应JSON字段:siteGoodsId,说明::门店维度的商品 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '对应JSON字段:goodsName,说明::商品名称。,示例值及对应分析:示例值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明::商品一级分类 ID。,示例值及对应分析:观测:当前 100 条样本中约有 5 个不同 ID,对应如“酒水类”“食品小吃类”“香烟类”等大类(仅从命名与商品名推断)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '对应JSON字段:goodsSecondCategoryId,说明::商品二级分类 ID。,示例值及对应分析:观测:样本中约有 7 个不同 ID,如饮料中的“矿泉水/功能饮料/碳酸饮料”等。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '对应JSON字段:unit,说明::库存计量单位。,示例值及对应分析:说明:库存数量(startNum、endNum、changeNum)均以这里的单位计数。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '对应JSON字段:price,说明::商品单价(单位金额)。,示例值及对应分析:观测特征:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '对应JSON字段:stockType,说明:(基于数据行为推断):,示例值及对应分析:1:出库类变动 典型情况是销售出库,库存减少 1 或 2;例如顾客点了一瓶饮料,对应一条 stockType=1, changeNum=-1 的记录。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '对应JSON字段:changeNum,说明::本次库存数量变化值。,示例值及对应分析:特点及取值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '对应JSON字段:startNum,说明::变动前(这次出入库之前)的库存数量。,示例值及对应分析:示例: 如记录:startNum = 28, changeNum = -1, endNum = 27。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '对应JSON字段:endNum,说明::变动后(出入库之后)的库存数量。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '对应JSON字段:changeNumA,说明::辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。,示例值及对应分析:结论: startNumA / endNumA / changeNumA 是为“一个商品有两种计量单位(如箱与瓶)”而设计的预留字段。 目前门店只在单一单位层面管理库存,故全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '对应JSON字段:startNumA,说明:(推测):辅助计量单位的起始库存(例如件/箱等第二单位)。,示例值及对应分析:当前门店在样本时间段内没有启用多单位库存管理,因此全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '对应JSON字段:endNumA,说明::辅助单位的变动后库存,同样未启用。,示例值及对应分析:?? goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '对应JSON字段:remark,说明::备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。,示例值及对应分析:当前样本中没有填入任何备注,但字段已预留,适用于盘点或手工调整场景。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '对应JSON字段:operatorName,说明::执行此次库存变动的操作人。,示例值及对应分析:观测值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '对应JSON字段:createTime,说明::这条库存变动记录的创建时间,即发生库存变更的时间点。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS '对应JSON字段:stock_goods_category_tree.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '对应JSON字段:id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '对应JSON字段:tenant_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '对应JSON字段:category_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '对应JSON字段:alias_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '对应JSON字段:pid,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '对应JSON字段:business_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '对应JSON字段:open_salesman,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '对应JSON字段:categoryBoxes,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '对应JSON字段:sort,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '对应JSON字段:is_warehousing,说明::分类节点主键 ID(在商品分类维度中的唯一标识)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS '对应JSON字段:goods_stock_summary.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '对应JSON字段:siteGoodsId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '对应JSON字段:goodsName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '对应JSON字段:goodsUnit,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '对应JSON字段:goodsCategorySecondId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '对应JSON字段:categoryName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '对应JSON字段:rangeStartStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '对应JSON字段:rangeEndStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '对应JSON字段:rangeIn,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '对应JSON字段:rangeOut,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '对应JSON字段:rangeSale,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '对应JSON字段:rangeSaleMoney,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '对应JSON字段:rangeInventory,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '对应JSON字段:currentStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS '对应JSON字段:payment_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '对应JSON字段:id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '对应JSON字段:site_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '对应JSON字段:siteProfile,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '对应JSON字段:relate_type,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '对应JSON字段:relate_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '对应JSON字段:pay_amount,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '对应JSON字段:pay_status,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '对应JSON字段:pay_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '对应JSON字段:create_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '对应JSON字段:payment_method,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS '对应JSON字段:refund_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '对应JSON字段:id,说明::本条 退款流水 的唯一 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,全系统维度标识该商户。,示例值及对应分析:特点:本文件中所有记录相同。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '对应JSON字段:tenantName,说明::租户(商户)名称。,示例值及对应分析:特点:本文件中固定为“朗朗桌球”,完全冗余于 siteProfile.shop_name。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:本文件中所有记录相同(单门店)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。包含字段包括但不限于:,示例值及对应分析:id:门店 ID(= site_id);';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '对应JSON字段:relate_type,说明::本退款对应的“业务类型”。,示例值及对应分析:结合支付记录的 relate_type 推测:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '对应JSON字段:relate_id,说明::本次退款关联的业务 ID。,示例值及对应分析:对于 relate_type = 2:应该对应某个订单/结算的主键;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '对应JSON字段:pay_sn,说明:?????? refund_transactions-Analysis.md,示例值及对应分析:?? refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '对应JSON字段:pay_amount,说明::本次退款的 资金变动金额。,示例值及对应分析:特征很重要:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):,示例值及对应分析:设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '对应JSON字段:round_amount,说明:(推测):,示例值及对应分析:舍入金额/抹零金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '对应JSON字段:pay_status,说明:(推测):,示例值及对应分析:支付/退款状态枚举:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '对应JSON字段:pay_time,说明::退款在支付渠道层面实际发生的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '对应JSON字段:create_time,说明::本条退款流水在系统内创建时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '对应JSON字段:payment_method,说明:(推测):,示例值及对应分析:支付/退款的 方式类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '对应JSON字段:pay_terminal,说明:(推测):,示例值及对应分析:退款所使用的 终端类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '对应JSON字段:pay_config_id,说明:(推测):,示例值及对应分析:支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:(推测):,示例值及对应分析:线上支付的 渠道编号,例如:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '对应JSON字段:online_pay_type,说明:(推测):,示例值及对应分析:在线退款的类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '对应JSON字段:channel_fee,说明:(推测):,示例值及对应分析:第三方支付渠道对本次退款收取的手续费;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '对应JSON字段:channel_payer_id,说明:(推测):,示例值及对应分析:支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '对应JSON字段:channel_pay_no,说明:(推测):,示例值及对应分析:第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '对应JSON字段:member_id,说明::,示例值及对应分析:租户内部的会员 ID(对应会员档案中的某个主键)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '对应JSON字段:member_card_id,说明::,示例值及对应分析:关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '对应JSON字段:cashier_point_id,说明:(推测):,示例值及对应分析:收银点 ID,例如前台 1、前台 2、自助机等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '对应JSON字段:operator_id,说明::,示例值及对应分析:执行该退款操作的操作员 ID。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '对应JSON字段:action_type,说明:(推测):,示例值及对应分析:行为类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '对应JSON字段:check_status,说明:(推测):,示例值及对应分析:审核状态:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '对应JSON字段:is_revoke,说明:(推测):,示例值及对应分析:是否撤销型退款/撤销原支付:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '对应JSON字段:balance_frozen_amount,说明:(推测):,示例值及对应分析:涉及会员储值卡退款时,暂时冻结的余额金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '对应JSON字段:card_frozen_amount,说明::与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。,示例值及对应分析:状态同上:本数据中未发生“卡冻结退款”。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS '对应JSON字段:platform_coupon_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '对应JSON字段:id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '对应JSON字段:verify_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '对应JSON字段:certificate_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '对应JSON字段:coupon_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '对应JSON字段:coupon_channel,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '对应JSON字段:groupon_type,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '对应JSON字段:group_package_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '对应JSON字段:sale_price,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '对应JSON字段:coupon_free_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '对应JSON字段:coupon_cover,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '对应JSON字段:coupon_remark,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '对应JSON字段:use_status,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '对应JSON字段:consume_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '对应JSON字段:create_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '对应JSON字段:deal_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '对应JSON字段:channel_deal_id,说明:任意一个 ID 字段缺失时(如部分记录 deal_id=0),仍然可以通过其他字段(coupon_name + sale_price + coupon_money + channel_deal_id)唯一识别该产品。,示例值及对应分析:这种多字段冗余,结构上提升了抗“配置缺失”的能力。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '对应JSON字段:site_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '对应JSON字段:site_order_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '对应JSON字段:table_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '对应JSON字段:operator_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '对应JSON字段:operator_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '对应JSON字段:is_delete,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS '对应JSON字段:tenant_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 tenant_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '对应JSON字段:id,说明::商品档案主键 ID,唯一标识一条商品。,示例值及对应分析:作用:作为其他业务表(销售明细、库存流水、门店商品表等)的外键,通常以 tenant_goods_id 或类似字段出现。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:和其它 JSON 中的 tenant_id / tenantId 一致,用于区分不同商户(本次数据只包含同一租户)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称(前台展示名称)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条码(EAN 等),目前未维护。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '对应JSON字段:categoryName,说明::商品一级分类名称(业务可读)。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '对应JSON字段:unit,说明::计量单位。,示例值及对应分析:取值(共 12 种左右):';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '对应JSON字段:goods_number,说明::商品内部编码(自定义货号/系统货号)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '对应JSON字段:goods_state,说明:(推测):商品状态(上架/下架等)。,示例值及对应分析:1:正常/上架;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明:(推测):销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。,示例值及对应分析:现有数据只有一个值,说明本门店目前仅通过一种渠道销售这些商品。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(推测):是否允许参与折扣/打折。,示例值及对应分析:1:允许折扣;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(推测):,示例值及对应分析:字面意思是“是否允许门店间调拨/门店级操作”:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效商品);';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明:(推测):是否启用库存管理。,示例值及对应分析:1:该商品纳入库存管理;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '对应JSON字段:isInSite,说明:(从命名推测):是否在当前门店启用/上架。,示例值及对应分析:现象:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '对应JSON字段:cost_price,说明::成本价格。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(推测):,示例值及对应分析:不同的成本价格来源或计算方式,如:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '对应JSON字段:market_price,说明::商品标价 / 售价(标准销售单价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::该商品允许售卖的最低价格(底价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '对应JSON字段:common_sale_royalty,说明:(推测):普通销售提成比例或提成金额的配置字段。,示例值及对应分析:当前门店未在商品档案上配置员工提成规则,全部为 0。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '对应JSON字段:point_sale_royalty,说明:(推测):积分销售提成/积分赠送规则相关配置。,示例值及对应分析:当前同样未启用。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::拼音首字母/助记码。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '对应JSON字段:commodityCode,说明::,示例值及对应分析:与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '对应JSON字段:commodity_code,说明::商品编码(通常为对外商品编码或条码)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品封面图片 URL 地址。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '对应JSON字段:supplier_id,说明::供应商 ID,用于关联到供应商档案。,示例值及对应分析:当前所有商品都未挂接具体供应商(或门店未使用供应链管理模块)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '对应JSON字段:remark_name,说明:(从命名推断):商品备注名/别名,通常用来配置简写或特殊显示名称。,示例值及对应分析:当前门店尚未使用该字段,字段设计为将来扩展预留。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '对应JSON字段:create_time,说明::商品档案创建时间。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '对应JSON字段:update_time,说明::商品档案最近一次修改时间。,示例值及对应分析:分布:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '对应JSON字段:group_buy_packages.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '对应JSON字段:id,说明::门店侧套餐 ID,本文件内部的主键。,示例值及对应分析:特点:17 条记录中均为不同的大整数 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '对应JSON字段:package_id,说明::“上层套餐 ID” 或“总部/系统级套餐 ID”。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '对应JSON字段:package_name,说明::团购套餐名称,用于前台展示和核销界面。,示例值及对应分析:示例:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '对应JSON字段:selling_price,说明:(结合字段命名):,示例值及对应分析:语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '对应JSON字段:coupon_money,说明::券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。,示例值及对应分析:示例(对应套餐名称):';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '对应JSON字段:date_type,说明:(推测):,示例值及对应分析:典型用法:区分“全部日期可用 / 工作日 / 周末 / 指定日期”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '对应JSON字段:date_info,说明:(推测):,示例值及对应分析:预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '对应JSON字段:start_time,说明::套餐开始生效的日期时间。,示例值及对应分析:示例:"2025-07-20 00:00:00" 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '对应JSON字段:end_time,说明::套餐失效的日期时间(到这个时间点后不可使用)。,示例值及对应分析:示例:形如 "2025-11-30 23:59:59",部分记录使用 9999-12-31 23:59:59 风格的极大日期表示长期有效(本数据中如有这种值,可解读为“长期有效”)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '对应JSON字段:start_clock,说明::每日可用起始时间点(第一段)。,示例值及对应分析:说明:配合 end_clock 使用,定义一个日内时段。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '对应JSON字段:end_clock,说明::每日可用的结束时间点(第一段)。,示例值及对应分析:结构说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '对应JSON字段:add_start_clock,说明:(推测):附加可用时间段的起始时间(第二段)。,示例值及对应分析:例如有的套餐可以在两个不连续的时段使用:早场 + 夜场,则可用第一段 start_clock / end_clock 和第二段 add_start_clock / add_end_clock 组合。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '对应JSON字段:add_end_clock,说明::附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。,示例值及对应分析:整体理解:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '对应JSON字段:duration,说明::套餐内包含的时长(秒)。,示例值及对应分析:与名称一致:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '对应JSON字段:usable_count,说明::可使用次数上限。,示例值及对应分析:数据特征说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '对应JSON字段:usable_range,说明:吻合(A区中八/B区中八/斯诺克/KTV/包厢等)。,示例值及对应分析:通过该关联,系统在核销时可以校验:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '对应JSON字段:table_area_id,说明:(推测):,示例值及对应分析:原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '对应JSON字段:table_area_name,说明::套餐适用的“门店台区名称”,用于显示和筛选。,示例值及对应分析:说明:这个字段是对区域 ID 维度的文字描述,便于直观理解。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '对应JSON字段:table_area_id_list,说明:(推测):,示例值及对应分析:用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明:(推测):,示例值及对应分析:与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '对应JSON字段:tenant_table_area_id_list,说明:(推测):,示例值及对应分析:实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:全表值相同,且与其他 JSON 文件中的 site_id 一致,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '对应JSON字段:site_name,说明::门店名称。,示例值及对应分析:观测值:全部为 "朗朗桌球"。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '对应JSON字段:tenant_id,说明::租户 ID(品牌/商户 ID)。,示例值及对应分析:特点:全表值相同,说明所有套餐定义属于同一商户(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '对应JSON字段:card_type_ids,说明:(推测):,示例值及对应分析:原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '对应JSON字段:group_type,说明:(推测):,示例值及对应分析:团购类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '对应JSON字段:system_group_type,说明:(推测):,示例值及对应分析:系统内对团购类型更底层的划分,比如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '对应JSON字段:type,说明:(推测):,示例值及对应分析:内部业务子类型,具体含义需要结合系统文档;仅从数据无法确定是“台费类 vs 包厢类”还是“平台套餐 vs 自定义套餐”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '对应JSON字段:effective_status,说明:(结合命名和数据特征推断):,示例值及对应分析:1:有效(在当前时间区间内、配置正常,可核销使用)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '对应JSON字段:is_enabled,说明::启用状态。,示例值及对应分析:从其他表的统一风格来看,1 一般表示“启用 / 上架”,2 表示“停用 / 下架”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '对应JSON字段:max_selectable_categories,说明:?????? group_buy_packages-Analysis.md,示例值及对应分析:?? group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '对应JSON字段:area_tag_type,说明:(推测):区域标记类型:,示例值及对应分析:1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '对应JSON字段:creator_name,说明::创建人信息,一般包含“角色:姓名”。,示例值及对应分析:示例:"管理员:郑丽珊"';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '对应JSON字段:create_time,说明::该套餐在系统中创建的时间。,示例值及对应分析:特点:每条记录各不相同,覆盖了 2025-07 至 2025-10 的创建时间。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS '对应JSON字段:group_buy_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '对应JSON字段:id,说明::本条“团购套餐流水”记录的 主键 ID。,示例值及对应分析:作用:唯一标识一条券使用到台费上的记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特点:全表值相同,说明所有记录属于同一租户。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,与其它 JSON 中一致。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '对应JSON字段:siteName,说明::门店名称,冗余展示用。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '对应JSON字段:table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '对应JSON字段:tableName,说明::本次使用券所关联的 球台名称/台号。,示例值及对应分析:关联:对应台桌列表中的 table_name / table_no,通过 table_id 进一步关联。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '对应JSON字段:tableAreaName,说明::该球台所属的 台区名称。,示例值及对应分析:关联:与台区配置中的 area_name 含义一致,与团购套餐定义中的 table_area_name 一致。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单 ID(小票结账主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:(推测):,示例值及对应分析:指向支付记录表中的支付流水 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单中“券使用记录”的 ID。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '对应JSON字段:order_coupon_channel,说明:(推测):,示例值及对应分析:券渠道类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明::团购券券码,核销时扫描/录入的字符串。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明::本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '对应JSON字段:coupon_origin_id,说明:(推测):,示例值及对应分析:平台/上游系统中的券记录主键 ID,“券来源 ID”。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '对应JSON字段:ledger_name,说明::台费侧关联的“团购项目名称”(记账名)。,示例值及对应分析:结构上通常来源于团购套餐定义的 package_name,或由系统在创建活动时生成。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。,示例值及对应分析:当前门店未对团购项目做进一步分组。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::本次券实际冲抵台费的金额。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '对应JSON字段:ledger_count,说明::按此次优惠实际计算的“核销秒数”。,示例值及对应分析:结构观察:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。,示例值及对应分析:作用:配合 ledger_count 用于计算这一条券在台费层面对应的金额(理论上应接近 = 单价 × 秒数/3600)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):流水状态。,示例值及对应分析:1:正常有效;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '对应JSON字段:table_charge_seconds,说明::本次结算中该球台总计计费的秒数(整台的台费计费时间)。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '对应JSON字段:promotion_activity_id,说明:(推测):团购/促销活动 ID。,示例值及对应分析:对应平台或内部促销活动的主键,每个活动通常绑定一个或多个具体套餐(promotion_coupon_id)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '对应JSON字段:promotion_coupon_id,说明::团购套餐定义 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '对应JSON字段:promotion_seconds,说明::团购套餐定义的“标准时长”(券本身标称的可用时长)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '对应JSON字段:offer_type,说明:(推测):优惠类型。,示例值及对应分析:在券适用多个优惠方式的系统中,一般用来区分“满减/折扣/代金券/套餐券”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '对应JSON字段:assistant_promotion_money,说明::分摊到“助教服务”的促销金额。,示例值及对应分析:当前场景下,团购券只与台费相关,未涉及助教的金额抵扣。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '对应JSON字段:assistant_service_promotion_money,说明::进一步细分助教服务的促销金额。,示例值及对应分析:当前未使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '对应JSON字段:table_service_promotion_money,说明::本次券使用中,分摊到“台费服务费”部分的促销金额。,示例值及对应分析:当前样本中,促销金额都在 ledger_amount 中体现,该字段未单独拆出。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '对应JSON字段:goods_promotion_money,说明::本次券使用中,分摊到“商品”部分的促销金额。,示例值及对应分析:当前数据中,所有团购券都只用于抵扣台费,没有用来抵扣商品,因此该字段为 0。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '对应JSON字段:recharge_promotion_money,说明::来自“充值类优惠”的分摊金额(例如储值赠送部分)。,示例值及对应分析:当前所有数据为 0,但结构上已经预留了“多来源促销金额分摊”的能力。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '对应JSON字段:reward_promotion_money,说明::本次促销中,属于“奖励金/积分抵扣”的金额。,示例值及对应分析:当前没有使用此维度的促销。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '对应JSON字段:goodsOptionPrice,说明:(按命名推测):商品规格价格,用于商品类促销分摊时使用。,示例值及对应分析:当前在“团购套餐流水”中未被实际使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织 ID。,示例值及对应分析:以上 4 个销售相关字段在当前门店的团购套餐使用中都未启用,仅作为结构预留。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员角色 ID。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员/业务员用户 ID。,示例值及对应分析:当前所有团购套餐流水都未指定独立的营业员。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '对应JSON字段:operator_id,说明::执行本次核销/结算操作的 操作员 ID。,示例值及对应分析:关联:可以与员工档案表中的 id 对应(当前导出中员工表未单独给出,但风格和其它表一致)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '对应JSON字段:operator_name,说明::操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独作为一条订单行。,示例值及对应分析:1:以独立条目方式进行结算(绝大部分记录如此)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '对应JSON字段:create_time,说明::本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。,示例值及对应分析:用法:可用于按时间范围过滤团购使用记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS '对应JSON字段:settlement_ticket_details.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '对应JSON字段:orderSettleId,说明::同 data.data.orderSettleId,为结算单 ID 的冗余。,示例值及对应分析:orderType';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '对应JSON字段:actualPayment,说明::本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。,示例值及对应分析:一般应与支付记录中各支付流水金额汇总相匹配。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '对应JSON字段:adjustAmount,说明::台费层面的人工调价金额(仅台费部分)。,示例值及对应分析:memberDiscountAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '对应JSON字段:assistantManualDiscount,说明::针对“助教项目”的人工减免金额汇总(整单维度)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '对应JSON字段:balanceAmount,说明::本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。,示例值及对应分析:对应 结账记录.json 的同名字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '对应JSON字段:cashierName,说明::本单结算操作员名称(带角色前缀文字)。,示例值及对应分析:对应员工维表中的某个账号,便于小票上展示“收银员:XXX”。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '对应JSON字段:consumeMoney,说明::本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。,示例值及对应分析:对应 结账记录.json 的 consumeMoney 字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '对应JSON字段:couponAmount,说明::本单由优惠券抵扣的金额汇总。,示例值及对应分析:结构上:应与 orderCouponLedgers.discountAmount 的合计存在关系,但当前导出未填充。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '对应JSON字段:deliveryAddress,说明::配送地址(若存在外送业务时使用)。,示例值及对应分析:对于球房场景,当前时间范围内未使用。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '对应JSON字段:deliveryFee,说明::配送费金额(如果支持外送业务)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '对应JSON字段:ledgerAmount,说明::按台账口径对应的金额,一般与 discountAmount 一致或有固定关系。,示例值及对应分析:rewardPromotionMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '对应JSON字段:memberDeductAmount,说明:(结构上):会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '对应JSON字段:memberOfferAmount,说明::由“会员权益/折扣”产生的优惠金额总计(整单维度)。,示例值及对应分析:与 memberProfile 以及台费/商品明细中的 memberDiscountAmount 有对应关系。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '对应JSON字段:onlineReturnAmount,说明::本单通过线上支付渠道退回的金额(如微信/支付宝退款)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '对应JSON字段:orderRemark,说明::订单备注,由收银员录入,用于记录与本单相关的特殊说明。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '对应JSON字段:orderSettleNumber,说明:(推测):结算单编号(与 ID 独立的一套编号体系,如流水号)。当前导出时间段内未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '对应JSON字段:payMemberBalance,说明:(结构上):使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '对应JSON字段:payTime,说明::本单最终支付成功时间。,示例值及对应分析:和 结账记录.json 中的 payTime 对应,一般与 支付记录.create_time/pay_time 在同一时间段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '对应JSON字段:paymentMethod,说明::结算主支付方式编码(汇总视角)。,示例值及对应分析:对应 结账记录.json 中的 paymentMethod 字段;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '对应JSON字段:pointDiscountCost,说明::积分抵扣对应的成本金额(成本侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '对应JSON字段:pointDiscountPrice,说明::积分抵扣对应的金额(售价侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '对应JSON字段:prepayMoney,说明::预付金/定金在本单中使用的金额。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '对应JSON字段:refundAmount,说明::本单涉及的退款金额(汇总)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '对应JSON字段:returnGoodsAmount,说明::本单涉及的退货金额汇总。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '对应JSON字段:rewardName,说明:(结构上):用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '对应JSON字段:settleType,说明::结算类型字符串标识。,示例值及对应分析:"SiteOrder":店内消费订单结算。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '对应JSON字段:siteAddress,说明::门店地址(详细地址)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '对应JSON字段:siteBusinessTel,说明::门店电话。,示例值及对应分析:用途:用于小票打印上的客服电话。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '对应JSON字段:siteName,说明::门店名称,如“朗朗桌球”。,示例值及对应分析:用途:小票上展示门店名。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '对应JSON字段:tenantId,说明::租户 / 商户 ID(品牌维度)。,示例值及对应分析:当前数据:恒定为同一值,表示所有记录都来自同一商户。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '对应JSON字段:tenantName,说明::租户名称,如“朗朗桌球”。,示例值及对应分析:当前数据:全表统一一个值。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '对应JSON字段:ticketCustomContent,说明::自定义小票内容,如商家自定义宣传语、条款等。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '对应JSON字段:ticketRemark,说明::小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '对应JSON字段:voucherMoney,说明::代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '对应JSON字段:memberProfile,说明::,示例值及对应分析:不是会员卡主键,而是本次结账时的会员信息快照;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '对应JSON字段:orderItem,说明::本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。,示例值及对应分析:下面专门展开 orderItem 及其子结构。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '对应JSON字段:tenantMemberCardLogs,说明:?????? settlement_ticket_details-Analysis.md,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS '对应JSON字段:store_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '对应JSON字段:id,说明::门店商品 ID,门店维度的商品主键。,示例值及对应分析:用途:在其它文件中经常以 site_goods_id 的名字出现,与这里的 id 一致,用来关联库存记录、销售记录等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。同一品牌下多个门店共享一个 tenant_id。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一家门店“朗朗桌球”),和其它 JSON 中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '对应JSON字段:siteName,说明::门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。,示例值及对应分析:2. 商品标识和分类维度';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户/品牌维度的商品 ID,相当于“全局商品 ID”。,示例值及对应分析:用途:用于跨门店或与“商品档案(商品档案.json)”对齐时使用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。,示例值及对应分析:用途:业务展示字段,历史流水里也会冗余存一份商品名。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条形码(如 EAN-13 编码),用于扫码销售。此字段设计为可填,但此店目前未配置。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '对应JSON字段:oneCategoryName,说明::一级分类名称,如“零食”“酒水”“服务费”等。,示例值及对应分析:说明:与 goods_category_id 一一对应,是易读文本字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '对应JSON字段:twoCategoryName,说明::二级分类名称,如“面”“洋酒”“纸巾”等。,示例值及对应分析:说明:与 goods_second_category_id 对应。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '对应JSON字段:unit,说明::商品计量单位(销售单位)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '对应JSON字段:sale_price,说明::商品标准销售价(挂牌价),单位为元。,示例值及对应分析:说明:实际结算时可能会打折或用券抵扣,但这个字段表示“定价”。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '对应JSON字段:cost_price,说明::商品成本价(单件成本)。,示例值及对应分析:观察:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(结合成本字段推测):,示例值及对应分析:1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::最低允许成交价(限价)。,示例值及对应分析:用法逻辑(推测):';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '对应JSON字段:safe_stock,说明::安全库存量(阈值),低于该值时系统可以提示补货。,示例值及对应分析:当前门店尚未设置安全库存,所以全部为 0,仅起到结构占位作用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '对应JSON字段:stock,说明::当前可用库存数量(以 unit 为单位)。,示例值及对应分析:特征:可以是 0(库存卖完),也可以非常大(例如纸巾、茶位费这种按“份”计的虚拟库存设定)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '对应JSON字段:stock_A,说明:(系统设计):副单位库存数量。如果商品存在双单位(例如箱/瓶),stock_A 通常用于记录副单位库存。当前门店没有启用副单位库存管理,因此为 0。,示例值及对应分析:batch_stock_quantity';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '对应JSON字段:sale_num,说明::在当前统计口径下的销售数量(总销量,单位同 unit)。,示例值及对应分析:特征:和 total_sales 完全一致(当前导出时的统计口径下),说明两者是同一统计周期。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '对应JSON字段:total_purchase_cost,说明::总采购成本,单位为元。,示例值及对应分析:当前数据:与 provisional_total_cost 完全相等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '对应JSON字段:total_sales,说明:(从命名看):累计销售数量。,示例值及对应分析:实际:当前数据中 total_sales == sale_num,说明此接口的统计区间 = “截至当前的全部历史”,因此数量一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '对应JSON字段:average_monthly_sales,说明::平均月销量(件/月),根据某个统计周期内的销售数据折算而来。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '对应JSON字段:enable_status,说明:(结合名称与常见编码):,示例值及对应分析:1:启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '对应JSON字段:audit_status,说明:(典型业务语义):,示例值及对应分析:2:审核通过。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '对应JSON字段:goods_state,说明:类型:int,枚举,示例值及对应分析:观察值:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效档案);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明::是否纳入库存管理。,示例值及对应分析:1:启用库存管理(会有出入库流水)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(结合命名):,示例值及对应分析:是否允许参与折扣。当前全部为 1,说明所有商品都允许打折。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(结合命名与值分布):,示例值及对应分析:表示是否允许跨门店调拨或跨站点共享库存。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '对应JSON字段:forbid_sell_status,说明:类型:int,枚举,示例值及对应分析:观察值:全部为 1。';
+COMMENT ON COLUMN billiards_ods.store_goods_master."freeze" IS '对应JSON字段:freeze,说明::冻结状态。,示例值及对应分析:0:未冻结;';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '对应JSON字段:send_state,说明:(命名趋近“上架状态/可售状态”):,示例值及对应分析:1:可销售/可下单。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '对应JSON字段:custom_label_type,说明:(推测):自定义标签类型。,示例值及对应分析:1:使用系统默认标签(未出现);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '对应JSON字段:option_required,说明:(推测):是否需要在销售时选择规格/选项。,示例值及对应分析:1:不要求额外选项(单规格商品);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明::销售渠道类型。,示例值及对应分析:常见模式:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '对应JSON字段:remark,说明::商品备注(可以写口味说明、供应商、注意事项等)。当前尚未使用。,示例值及对应分析:sort';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::商品名称的拼音首字母缩写,有时多个别名用逗号分隔。,示例值及对应分析:作用:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '对应JSON字段:create_time,说明::门店商品档案创建时间(商品在门店建立档案的时间点)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '对应JSON字段:update_time,说明::最后一次修改该商品档案的时间(包括价格调整、状态变更等)。,示例值及对应分析:days_available';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS '对应JSON字段:store_goods_sales_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '对应JSON字段:id,说明::本条「门店销售流水」记录的主键 ID。,示例值及对应分析:用途:在系统内部唯一标识这一条销售明细。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特征:所有记录为同一个值,对应「非球科技系统中你的商户」。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '对应JSON字段:site_id,说明::门店 ID(系统主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '对应JSON字段:site_goods_id,说明::门店商品 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户(品牌)级商品 ID(全局商品 ID)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '对应JSON字段:order_settle_id,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '对应JSON字段:order_trade_no,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '对应JSON字段:order_goods_id,说明::订单商品明细 ID(订单内部的商品行主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:连接到「支付记录」中的一条支付流水,再通过支付的 relate_type/relate_id 把支付和订单、充值等业务区分开。,示例值及对应分析:对于退款,则通过退款记录里的 relate_type/relate_id 反向关联到原来的订单或支付。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单级优惠券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '对应JSON字段:ledger_name,说明::销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。,示例值及对应分析:说明:业务展示用字段,历史流水即使商品改名,这里会保留当时的名字。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明::销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::原始应收金额,公式上接近 ledger_unit_price × ledger_count。,示例值及对应分析:说明:这是未考虑优惠前的金额基础,用于后续计算折扣和抵扣。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '对应JSON字段:ledger_count,说明::销售数量(以 unit 为单位,unit 字段在门店商品档案中)。,示例值及对应分析:观测值:如 1, 2, 3, 6, 36 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::商品在该次销售中的「结算单价」(元/单位)。,示例值及对应分析:观测值示例:5.0, 8.0, 2.0, 10.0, 72.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '对应JSON字段:ledger_status,说明::销售流水状态。,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '对应JSON字段:discount_money,说明::本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。,示例值及对应分析:典型关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::被优惠券 / 团购券直接抵扣到这条商品明细上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员身份(会员折扣)针对这一行商品产生的优惠金额。,示例值及对应分析:说明:尽管字段存在,但当前实际折扣可能合并反映在 discount_money 中,这个字段没有拆开体现。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '对应JSON字段:option_coupon_deduct_money,说明::由优惠券抵扣“选项价格”的金额。,示例值及对应分析:上面这三个 option_* 字段,是为“主商品 + 选项”的更复杂计价方式预留的,本店当前所有记录都是单规格,选项体系未启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '对应JSON字段:option_member_discount_money,说明::由会员折扣作用在“选项价格”上的优惠金额。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '对应JSON字段:point_discount_money,说明::由积分抵扣的金额(顾客兑换积分抵现金额)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '对应JSON字段:point_discount_money_cost,说明::积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '对应JSON字段:real_goods_money,说明::商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。,示例值及对应分析:观测值:5.0, 10.0, 8.0, 6.0, 4.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '对应JSON字段:cost_money,说明::本条销售对应的成本金额(以元计)。,示例值及对应分析:观测示例:0.01, 0.00, 3.58, 1.79, 0.64 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '对应JSON字段:push_money,说明::本条销售对应的提成金额(给营业员/促销员的提成)。,示例值及对应分析:在启用营业员体系时,这里才会出现正数。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '对应JSON字段:sales_type,说明::销售类型。,示例值及对应分析:1:正常销售;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '对应JSON字段:is_single_order,说明::是否单独订单标识。,示例值及对应分析:1:作为独立明细参与某个订单结算;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '对应JSON字段:goods_remark,说明::商品备注/口味说明/特殊说明。,示例值及对应分析:用途:点单时如果需要额外说明,可以写在这里。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '对应JSON字段:option_price,说明::商品选项(规格/加料)的附加价格。,示例值及对应分析:说明:如加冰、加料、升级大杯等产生附加费用时,理论上应该体现到这里。当前门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '对应JSON字段:option_value_name,说明::商品选项名称(如规格、口味:大杯/小杯,不加冰等)。,示例值及对应分析:结构用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '对应JSON字段:option_name,说明:?????? store_goods_sales_records-Analysis.md,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '对应JSON字段:member_coupon_id,说明::会员券 ID(比如会员专享优惠券)。,示例值及对应分析:当前数据未使用,属于为会员权益预留的字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '对应JSON字段:package_coupon_id,说明::套餐券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:当前门店全部为 0,说明未启用这套销售员分组织的体系。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员的系统角色 ID(例如某个角色代码表示“销售员”)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID(系统账号 ID)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入这笔销售的员工)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,文字冗余。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '对应JSON字段:openSalesman,说明:(结合系统其它文件推断):,示例值及对应分析:1:启用“营业员/销售员”机制(要指定 salesman);';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:非 0:销售记录关联到具体某张桌台(例如顾客在台上点饮料)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明::租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。,示例值及对应分析:2.2 门店 / 球台维度字段';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '对应JSON字段:tenant_goods_category_id,说明::租户级商品一级分类 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '对应JSON字段:create_time,说明::销售记录创建时间,通常就是结账时间或录入时间。,示例值及对应分析:用途:用于按时间维度查询销售流水,与订单层的时间字段对齐。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
diff --git a/etl_billiards/feiqiu-ETL.code-workspace b/tmp/etl_billiards_misc/feiqiu-ETL.code-workspace
similarity index 100%
rename from etl_billiards/feiqiu-ETL.code-workspace
rename to tmp/etl_billiards_misc/feiqiu-ETL.code-workspace
diff --git a/etl_billiards/.env.example b/tmp/etl_billiards_misc/tmp & Delete/.env.example
similarity index 100%
rename from etl_billiards/.env.example
rename to tmp/etl_billiards_misc/tmp & Delete/.env.example
diff --git a/DWD层设计建议.docx b/tmp/etl_billiards_misc/tmp & Delete/DWD层设计建议.docx
similarity index 100%
rename from DWD层设计建议.docx
rename to tmp/etl_billiards_misc/tmp & Delete/DWD层设计建议.docx
diff --git a/tmp/etl_billiards_misc/tmp & Delete/DWD层设计草稿.md b/tmp/etl_billiards_misc/tmp & Delete/DWD层设计草稿.md
new file mode 100644
index 0000000..e5603e0
--- /dev/null
+++ b/tmp/etl_billiards_misc/tmp & Delete/DWD层设计草稿.md
@@ -0,0 +1,1373 @@
+# 台球厅数仓 DWD 层数据库说明书
+本说明书详细列出了台球厅经营系统的 DWD 层表结构。
+每张表都包含字段名称、数据类型、来源、含义、是否属于主键/外键、以及枚举值解释。说明书依据《*-Analysis.md》中提供的字段说明整理完成,未出现省略号,确保字段信息完整可追溯。
+因业务需求,将一个表拆成主数据表和扩展数据表(Ex为后缀),如:维度表的门店数据表分为主表dim_site 和扩展表dim_site_Ex,主键相同,作为唯一关联标识。在业务代码处理的读和写时,使用统一处理方式,将数据视为一个表格。注意,极少数表,没有扩展表。
+**注意:考虑到后期分布式部署,以及测试的便利性。所有的“外键”的处理,使用业务处理,不在数据库中强制约束。**
+
+
+## 维度表(DIM)
+
+### 门店维度表
+提取自各 ODS 中的 siteProfile 对象,如table_fee_transactions。记录门店的基本信息和配置,是其他事实表的外键。
+
+**dim_site**
+|数据库字段名|字段类型|来源字段(table_fee_transactions.siteProfile)|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|site_id|bigint|id|门店主键 ID。与各事实表中的 site_id 一致,用于唯一标识一个门店。|主键|
+|org_id|bigint|org_id|组织 ID,例如品牌总部或上级组织标识。后续可关联组织维度,用于按组织层级统计。|外键|
+|tenant_id|bigint|tenant_id|租户 ID(品牌商户 ID)。在多租户部署时区分不同品牌或老板。|外键|
+|shop_name|varchar(255)|shop_name|门店名称,例如“朗朗桌球”。用于展示和按门店统计。|-|
+|site_label|varchar(20)|site_label|门店标签,例如“A”。通常用于内部分类或标记门店类型/版本,具体含义需业务确认。|-|
+|full_address|varchar(500)|full_address|门店详细地址,包含省市区及街道门牌号,用于地理展示与导航。|-|
+|address|varchar(255)|address|简化地址描述,例如门店简称地址或商圈描述。便于在列表或报表中展示。|-|
+|longitude|decimal(10,6)|longitude|门店经度坐标。可与 latitude 一起用于地图展示和地理分析。|-|
+|latitude|decimal(10,6)|latitude|门店纬度坐标。与 longitude 配对使用。|-|
+|tenant_site_region_id|bigint|tenant_site_region_id|区域行政编码或租户定义的区域编码,用于区域分组(如城市、商圈)。具体编码体系需业务确认。|外键|
+|business_tel|varchar(50)|business_tel|门店联系电话,用于展示和客服联系。|-|
+|site_type|tinyint|site_type|门店类型枚举字段,例如直营店、加盟店、体验店等。具体取值含义在样本中未给出,但对按门店类型分层分析可能重要。|-|
+|shop_status|tinyint|shop_status|门店营业状态。当前样本中取值为 1 表示营业;其他取值(如 0)可能代表停业或关店,具体编码需业务确认。对分析是否纳入门店统计非常重要。|-|
+
+
+**dim_site_Ex**
+|数据库字段名|字段类型|来源字段(table_fee_transactions.siteProfile)|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|site_id|bigint|id|门店主键 ID。与各事实表中的 site_id 一致,用于唯一标识一个门店。|主键|
+|auto_light|tinyint|auto_light|是否启用自动控灯。取值:0 表示不自动控灯;1 表示自动控灯。主要用于门店设备控制,不直接影响经营分析。|-|
+|attendance_enabled|tinyint|attendance_enabled|是否启用考勤功能。取值:0 表示未启用考勤;1 表示启用考勤(助教/员工需在门店打卡)。可用于人力管理分析。|-|
+|attendance_distance|int|attendance_distance|考勤打卡允许范围(单位通常为米),控制员工在多大范围内可以完成打卡。当前样本中多为 0,具体阈值含义需业务确认。|-|
+|prod_env|tinyint|prod_env|环境标记字段,用于区分测试环境与生产环境。样本中仅出现 1,表示生产环境,其他取值含义需与业务系统确认。|-|
+|light_status|tinyint|light_status|灯控状态标记,由门店灯控系统使用。具体枚举取值和业务含义未在文档中说明,例如是否表示“已接入/未接入”“开灯/关灯”等。|-|
+|light_type|tinyint|light_type|灯控类型配置,用于区分不同灯控设备或协议。具体枚举值及含义未在样本中说明。|-|
+|light_token|varchar(255)|light_token|灯控系统访问令牌或密钥,用于设备控制鉴权。对数据分析无直接作用。|-|
+|avatar_url|varchar(500)|avatar|门店头像图片 URL,用于前端展示门店图片或 logo。|-|
+|wifi_name|varchar(100)|wifi_name|门店 WiFi 名称,用于对外展示或员工内部查看。|-|
+|wifi_password|varchar(100)|wifi_password|门店 WiFi 密码,仅用于员工或顾客上网便利配置。|-|
+|customer_service_qrcode|varchar(500)|customer_service_qrcode|客服二维码图片 URL,例如微信客服或服务号二维码。便于前端展示。|-|
+|customer_service_wechat|varchar(100)|customer_service_wechat|客服微信号或客服联系方式,用于展示与沟通。|-|
+|fixed_pay_qrcode|varchar(500)|fixed_pay_qrCode|固定收款码二维码图片 URL(如收款静态码)。用于前端展示,不参与折扣或经营计算。|-|
+
+
+**dim_site 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|site_id|主键|-|-|主键字段|
+|org_id|外键|dim_organization|org_id|组织 ID,用于关联组织维度。|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID,用于区分不同品牌或老板。|
+|tenant_site_region_id|外键|dim_region|region_id|区域 ID,用于区域分组。|
+
+
+
+### 台桌维度表
+来自 site_tables_master。每行代表一张球台或包厢,包含区域和业务角色信息。
+
+**dim_table**
+|数据库字段名|字段类型|来源字段|说明(含枚举值与取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|table_id|bigint|id|台桌主键 ID,全局唯一,用于关联所有与台相关的流水(台费、助教、台费打折等)。|主键|
+|site_id|bigint|site_id|门店 ID,对应门店维表 dim_site.site_id。本样本中全部为同一门店,但结构上支持多门店。|外键|
+|site_table_area_id|bigint|site_table_area_id|台桌所属区域 ID。与同一门店下的 area_name 一一对应,用于区分 A区/B区/包厢等业务区域。后续可抽象为区域维表主键。|-|
+|area_name|varchar(64)|areaName|区域名称。样例枚举:A区、B区、补时长、C区、麻将房、VIP包厢、斯诺克区、K包、666、M7、k包活动区、TV台、M8、发财 等。用于前台展示与区域分析。|-|
+|table_name|varchar(64)|table_name|台号/台名称。样例:A1~A18,B1~B6,S1~S4,VIP1、VIP2、VIP3、VIP5,TV台,M7,M8,666,888,发财,常乐,幸会(纯k),董事办,补时长*,大包、小包 等。|-|
+|table_status|tinyint|table_status|台当前状态(运行状态)。枚举:1=空闲中,2=使用中,3=暂停中。用于实时/历史台位利用率分析。|-|
+|table_status_name|varchar(32)|tableStatusName|台状态的中文名称。当前枚举:空闲中、使用中、暂停中。为 table_status 的冗余展示字段。|-|
+|show_status|tinyint|show_status|台在前台列表中的展示控制(推测)。样例分布:1=在普通开台列表中展示(大多数台),2=不在普通列表展示,多用于特殊房间(如“大包”“小包”)。一般与 is_online_reservation 组合使用来区分“线下台/线上预约房”。|-|
+|create_time|datetime|create_time|台配置的创建时间(或最近一次复制/创建时间)。可用于分析门店台桌配置变更历史。本样本多集中在某几个日期批量创建。|-|
+
+**dim_table_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值与取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|table_id|bigint|id|台桌主键 ID,全局唯一,用于关联所有与台相关的流水(台费、助教、台费打折等)。|主键|
+|table_price|decimal(10,2)|table_price|台基础单价字段(理论上用于按台配置单价)。本门店样本全部为 0.00,实际计费来自其他计价策略表或规则。暂不参与真实计费逻辑。|-|
+|virtual_table|tinyint|virtual_table|虚拟台标记(推测)。枚举推测:0=物理台(实体球台/包厢),1=虚拟台(如合台、补钟虚拟台等)。样本数据全部为 0,系统实际是通过“特殊台名+计费逻辑”实现补时等功能,本字段当前未实际使用。|-|
+|self_table|tinyint|self_table|自有台标记(推测)。枚举推测:1=本门店自有台,0=非自有/联营等场景。样本数据全部为 1,暂未体现非自营台。当前对分析影响有限。|-|
+|is_rest_area|tinyint|is_rest_area|休息区标记(推测)。枚举推测:0=普通计费区域,1=休息区(可能不计费或计费逻辑不同)。样本数据全部为 0,未实际使用。|-|
+|light_status|tinyint|light_status|灯光状态(推测)。结合命名和取值:1=开灯/可用,2=关灯/关闭。本样本大部分为 2(灯关),少数为 1。主要用于与智能灯控硬件联动,对经营分析一般不直接使用。|-|
+|delay_lights_time|int|delay_lights_time|灯光延迟关闭时间(推测,单位秒或分钟)。当前全部为 0,说明未启用“结账后延迟关灯”功能。具体单位需与业务确认。|-|
+|temporary_light_second|int|temporary_light_second|临时点灯时长(推测,单位秒)。例如前台手动开启临时灯光一段时间。本样本全部为 0,功能未启用。|-|
+|audit_status|tinyint|audit_status|台配置审核状态。枚举(结合命名惯例):2=已审核/已生效;其他值可能表示待审核/驳回(样本未出现)。样本所有台均为 2。在分析时通常过滤 audit_status != 2 的台。|-|
+|charge_free|tinyint|charge_free|免单台标记(推测)。枚举推测:0=正常计费台,1=免单/不计费台。样本数据全部为 0,门店未配置免单台。含义未在其它文档中完全确认。|-|
+|order_delay_time|int|order_delay_time|订单层面允许的自动延时时长(推测,单位秒或分钟),例如到点后自动延长计费。样本全部为 0,未启用此功能,具体业务规则待确认。|-|
+|table_cloth_use_time|int|table_cloth_use_time|台呢累计使用时长。结合数值特征,极大概率单位为秒(例如 1,863,727 ≈ 517 小时)。用于维护/更换台呢的寿命统计。|-|
+|table_cloth_use_cycle|int|table_cloth_use_Cycle|台呢使用周期阈值(推测,单位秒或小时),例如达到一定秒数后提醒更换。当前样本全部为 0,表示未设置阈值。实际规则未确认。|-|
+|is_online_reservation|tinyint|is_online_reservation|是否允许线上预约。样例分布:1=允许线上预约(如“大包”“小包”),2=不允许线上预约(普通台)。通常与 show_status 组合决定台的业务角色(线下散客台 vs 线上预约房)。|-|
+|only_allow_groupon|tinyint|only_allow_groupon|是否仅允许团购券使用(推测)。枚举推测:1=仅团购使用,2=不限(团购/非团购均可)。样本全部为 2,表示未设置“团购专用台”。规则未完全确认。|-|
+|applet_qrcode_url|varchar(512)|appletQrCodeUrl|小程序二维码 URL,每张台一条,用于打印二维码贴在台上,支持顾客扫码呼叫服务、查看账单、发起线上预约等。对数仓分析一般不需要,仅在精细化运营或运维排查时偶尔使用。|-|
+|site_name|varchar(128)|siteName|门店名称快照,样本为 "朗朗桌球"。冗余字段,展示用,门店名称应以 dim_site 为准。|-|
+
+
+**dim_table 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|table_id|主键|-|-|主键字段|
+|site_id|外键|dim_site|site_id|门店 ID,关联到 dim_site 表的 site_id。|
+|site_table_area_id|外键|dim_area|area_id|台桌区域 ID,关联到 dim_area 表的 area_id。|
+
+
+
+### 助教档案维表
+对应 assistant_accounts_master。每行代表一位助教账号及其人事/账号状态。
+
+**dim_assistant**
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|assistant_id|bigint|id|助教账号 ID,关联助教服务流水表。|主键|
+|user_id|bigint|user_id|系统用户 ID,用于统一跨模块身份。|外键|
+|assistant_no|varchar|assistant_no|助教工号/编号,业务识别用。|-|
+|real_name|varchar|real_name|助教真实姓名。|-|
+|nickname|varchar|nickname|前台展示昵称。|-|
+|mobile|varchar|mobile|手机号码。|-|
+|tenant_id|bigint|tenant_id|租户 ID。|外键|
+|site_id|bigint|site_id|门店 ID。|外键|
+|team_id|bigint|team_id|助教团队 ID。|外键|
+|team_name|varchar|team_name|团队名称。|-|
+|level|int|level|助教等级:8=管理员、10=初级、20=中级、30=高级、40=专家。|-|
+|entry_time|datetime|entry_time|入职时间。|-|
+|resign_time|datetime|resign_time|离职时间;远未来日期表示在职。|-|
+|leave_status|int|leave_status|在职状态:0=在职,1=已离职。|-|
+|assistant_status|int|assistant_status|账号启用状态:1=启用,2=停用/冻结。|-|
+
+
+**dim_assistant_Ex**
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|assistant_id|bigint|id|助教账号 ID,关联助教服务流水表。|主键|
+|gender|int|gender|性别枚举:0=未填/保密,1=男,2=女。|-|
+|birth_date|datetime|birth_date|出生日期,默认为 0001-01-01 表示未设置。|-|
+|avatar|varchar|avatar|头像 URL。|-|
+|introduce|varchar|introduce|个人简介文案(目前为空)。|-|
+|video_introduction_url|varchar|video_introduction_url|视频介绍 URL。|-|
+|height|float|height|身高(厘米),0 表示未填。|-|
+|weight|float|weight|体重(公斤),0 表示未填。|-|
+|shop_name|varchar|shop_name|门店名称。|-|
+|group_id|bigint|group_id|上级分组 ID,未使用。|-|
+|group_name|varchar|group_name|上级分组名称,空。|-|
+|person_org_id|bigint|person_org_id|人事组织 ID,用于权限和报表分组。|-|
+|staff_id|bigint|staff_id|预留员工 ID(全部为0)。|-|
+|staff_profile_id|bigint|staff_profile_id|外部人事档案 ID(全部为0)。|-|
+|assistant_grade|float|assistant_grade|平均评分(0 表示暂无)。|-|
+|sum_grade|float|sum_grade|总评分累加值。|-|
+|get_grade_times|int|get_grade_times|累计评分次数。|-|
+|charge_way|int|charge_way|计费方式:2=计时,其他未出现。|-|
+|allow_cx|int|allow_cx|是否允许促销计费:1=允许。|-|
+|is_guaranteed|int|is_guaranteed|是否有保底:1=是。|-|
+|salary_grant_enabled|int|salary_grant_enabled|薪资发放开关(值2,具体含义未知)。|-|
+|entry_type|int|entry_type|入职类型:1=正式;其他未出现。|-|
+|entry_sign_status|int|entry_sign_status|入职签约状态:0=未签约,1=已签约(未出现)。|-|
+|resign_sign_status|int|resign_sign_status|离职签约状态,未出现非 0。|-|
+|work_status|int|work_status|工作状态:1=在岗,2=离岗。与 leave_status 呼应。|-|
+|show_status|int|show_status|前台展示状态:1=显示;其他值未出现。|-|
+|show_sort|int|show_sort|前端排序序号。|-|
+|online_status|int|online_status|在线状态:1=在线。|-|
+|is_delete|int|is_delete|逻辑删除标记:0=未删除,1=已删除。|-|
+|criticism_status|int|criticism_status|投诉状态:1=正常,2=有投诉。|-|
+|create_time|datetime|create_time|账号创建时间。|-|
+|update_time|datetime|update_time|账号最近修改时间。|-|
+|start_time|datetime|start_time|配置生效开始时间。|-|
+|end_time|datetime|end_time|配置生效结束时间。|-|
+|last_table_id|bigint|last_table_id|最近服务的台桌 ID(未必存在)。|-|
+|last_table_name|varchar|last_table_name|最近服务球台名称。|-|
+|last_update_name|varchar|last_update_name|最近更新该账号的管理员。|-|
+|order_trade_no|bigint|order_trade_no|最近关联的订单号(非外键,仅做展示)。|-|
+|ding_talk_synced|int|ding_talk_synced|是否同步钉钉:1=已同步。|-|
+|site_light_cfg_id|bigint|site_light_cfg_id|灯控配置 ID(未启用)。|-|
+|light_equipment_id|varchar|light_equipment_id|灯控设备 ID(未启用)。|-|
+|light_status|int|light_status|灯控状态(值2,具体含义未知)。|-|
+|is_team_leader|int|is_team_leader|是否团队长:0=否,1=是。|-|
+|serial_number|bigint|serial_number|系统内部生成的序列号/排序标识,用于全局排序或历史迁移。| |
+|system_role_id|INT|system_role_id|系统角色 ID。观测值全为 10,具体角色含义未在文档中给出,无法判断业务含义。| |
+|pd_unit_price|DECIMAL(10,2)|pd_unit_price|标准单价(例如普通时段单价)配置。当前全部为 0,本门店未在账号层面定义单价,实际单价可能在商品/套餐配置中。|-|
+|cx_unit_price|DECIMAL(10,2)|cx_unit_price|促销时段单价,当前全部为 0,未在账号维度启用。|-|
+|job_num|VARCHAR(50)|job_num|备用工号字段。本数据中全部为空,当前门店未启用此工号体系。| |
+
+
+**dim_assistant 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|assistant_id|主键|-|-|主键字段|
+|user_id|外键|dim_user|user_id|系统用户 ID,用于统一跨模块身份。|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID,用于区分不同品牌或老板。|
+|site_id|外键|dim_site|site_id|门店 ID,关联到 dim_site 表的 site_id。|
+|team_id|外键|dim_team|team_id|助教团队 ID。|
+
+------------------------------------------------------------
+
+### 会员档案维表
+对应 member_profiles。每行记录租户内某会员的主档信息,包括等级、状态、注册信息等。
+
+**dim_member**
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|member_id|bigint|id|租户内会员主键。|主键|
+|system_member_id|bigint|system_member_id|跨租户全局会员 ID。|外键|
+|tenant_id|bigint|tenant_id|租户 ID。|外键|
+|register_site_id|bigint|register_site_id|注册门店 ID。|外键|
+|mobile|varchar|mobile|会员手机号。|-|
+|nickname|varchar|nickname|昵称(未必是真实姓名)。|-|
+|member_card_grade_code|int|member_card_grade_code|会员等级代码:1=金卡?2=银卡?3=钻石卡?4=黑卡?(按照 MD 文档枚举)。|-|
+|member_card_grade_name|varchar|member_card_grade_name|等级名称,中文描述。|-|
+|create_time|datetime|create_time|会员档案创建时间。|-|
+| | | | | |
+
+
+
+**dim_member_Ex**
+
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|member_id|bigint|id|租户内会员主键。|主键|
+|referrer_member_id|bigint|referrer_member_id|推荐人会员 ID,营销分析用。|-|
+|point|decimal|point|积分余额(暂未启用)。|-|
+|register_site_name|varchar|site_name|注册门店名称。|-|
+|growth_value|decimal|growth_value|成长值,暂未启用。|-|
+|user_status|int|user_status|会员状态枚举:1=正常,其它值未出现。|-|
+|status|int|status|帐户状态:1=正常;其它值未出现。|-|
+
+
+**dim_member 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|member_id|主键|-|-|主键字段|
+|system_member_id|外键|dim_system_member|system_member_id|跨租户全局会员 ID。|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID。|
+|register_site_id|外键|dim_site|site_id|注册门店 ID。|
+
+### 已开通的会员卡账户视图
+
+来自 member_stored_value_cards。每行代表一张会员卡账户的快照,记录卡种、持卡人、余额、有效期及各种折扣/扣款配置。
+重要说明:本视图不仅包含储值卡,还囊括活动抵用券、台费卡、酒水卡、月卡等多种卡种。
+大多数折扣/扣款字段在当前数据中保持默认值(如 10.0 表示不打折、100.0 表示全额抵扣、0 表示不启用),业务上暂未使用,但为系统预留能力。
+
+**dim_member_card_account**
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|member_card_id|bigint|id|会员卡账户主键,唯一标识一张具体卡。|主键|
+|tenant_id|bigint|tenant_id|租户/品牌 ID,用于分隔不同业务主体。|外键|
+|register_site_id|bigint|register_site_id|开卡门店 ID,对应 dim_site.site_id。|外键|
+|tenant_member_id|bigint|tenant_member_id|对应会员档案中的 member_id(本租户内)。0 表示未绑定会员。|外键|
+|system_member_id|bigint|system_member_id|全局会员 ID,用于跨租户统一会员身份。0 表示未绑定会员。|外键|
+|card_type_id|bigint|card_type_id|卡种 ID,指向卡种配置表。与下面的 grade_code 共同定义卡类别。|外键|
+|member_card_grade_code|bigint|member_card_grade_code|卡等级/卡类代码,区别不同类别卡。2790683528022853=储值卡,2790683528022856=活动抵用券,2790683528022855=台费卡,2790683528022858=酒水卡,2790683528022857=月卡|-|
+|member_card_grade_code_name|varchar|member_card_grade_code_name|卡等级中文名称,与 member_card_grade_code 一一对应。|-|
+|member_card_type_name|varchar|member_card_type_name|卡类型名称,通常与 grade_code_name 相同,纯展示字段。|-|
+|member_name|varchar|member_name|持卡会员姓名快照,部分为空表示未绑定。|-|
+|member_mobile|varchar|member_mobile|持卡会员手机号快照。|-|
+|balance|decimal|balance|当前余额或额度。对储值卡表示余额,对其他卡表示剩余金额或次数。|-|
+|start_time|datetime|start_time|卡片有效期开始时间。|-|
+|end_time|datetime|end_time|卡片有效期结束时间。|-|
+|last_consume_time|datetime|last_consume_time|最近一次消费时间;若为 "1970-01-01" 表示未消费过。|-|
+|status|int|status|卡状态:1=正常可用;4=过期/停用。其他值在数据中未出现。|-|
+|is_delete|int|is_delete|逻辑删除标记:0=未删除;1=已删除。|-|
+
+
+
+**dim_member_card_account_Ex**
+
+|数据库字段名|字段类型|来源字段|说明|关键角色|
+|---|---|---|---|---|
+|member_card_id|bigint|id|会员卡账户主键,唯一标识一张具体卡。|主键|
+|site_name|varchar|site_name|门店名称展示字段(全部相同)。|-|
+|tenant_name|varchar|tenantName|租户名称(当前导出为空)。|-|
+|tenant_avatar|varchar|tenantAvatar|租户头像 URL(当前导出为空)。|-|
+|effect_site_id|bigint|effect_site_id|卡片限定生效门店 ID。0 表示不限门店,配合 able_cross_site=1 表示全店通用。|-|
+|able_cross_site|int|able_cross_site|是否允许跨门店使用该卡:1=允许跨店;0=仅限开卡门店。|-|
+|card_physics_type|int|card_physics_type|物理卡类型:1=实体/标准卡;其他值未出现,含义未知。|-|
+|card_no|varchar|card_no|物理卡号或条码(当前全部为空)。|-|
+|bind_password|varchar|bind_password|卡绑定密码(未启用)。|-|
+|use_scene|varchar|use_scene|使用场景说明(当前为空)。|-|
+|denomination|decimal|denomination|面额或初始储值额度(当前均为0.0,未启用)。|-|
+|create_time|datetime|create_time|卡片创建时间。|-|
+|disable_start_time|datetime|disable_start_time|卡片禁用开始时间,当前为默认值表示未禁用。|-|
+|disable_end_time|datetime|disable_end_time|卡片禁用结束时间,当前为默认值表示未禁用。|-|
+|is_allow_give|int|is_allow_give|是否允许转赠给他人:0=不允许;1=允许。|-|
+|is_allow_order_deduct|int|is_allow_order_deduct|是否允许在订单层面统一扣款:0=不允许;1=允许。|-|
+|sort|int|sort|前端排序序号。|-|
+|table_discount|float|table_discount|台费折扣率(折扣百分比,10.0=不打折,9.0=九折等)。当前全部 10.0。|-|
+|goods_discount|float|goods_discount|商品折扣率,当前为 10.0 表示无折扣。|-|
+|assistant_discount|float|assistant_discount|助教服务折扣率,当前为 10.0。|-|
+|assistant_reward_discount|float|assistant_reward_discount|助教奖励折扣率,当前为 10.0(未启用)。|-|
+|table_service_discount|float|table_service_discount|台费服务类折扣率,当前为 10.0。|-|
+|goods_service_discount|float|goods_service_discount|商品服务折扣率,当前为 10.0。|-|
+|assistant_service_discount|float|assistant_service_discount|助教服务类折扣率,当前为 10.0。|-|
+|coupon_discount|float|coupon_discount|使用券的折扣比例(全部 10.0,未使用)。|-|
+|table_discount_sub_switch|int|table_discount_sub_switch|台费折扣叠加开关:1=叠加其他折扣;2=不叠加,仅用卡折扣。|-|
+|goods_discount_sub_switch|int|goods_discount_sub_switch|商品折扣叠加开关,意义同上。|-|
+|assistant_discount_sub_switch|int|assistant_discount_sub_switch|助教折扣叠加开关,意义同上。|-|
+|assistant_reward_discount_sub_switch|int|assistant_reward_discount_sub_switch|助教奖励折扣叠加开关(未启用)。|-|
+|goods_discount_range_type|int|goods_discount_range_type|商品折扣范围类型,未在文档说明具体含义。|-|
+|table_deduct_radio|float|table_deduct_radio|台费抵扣比例(百分比)。100.0 表示允许全额抵扣;0=不允许。|-|
+|goods_deduct_radio|float|goods_deduct_radio|商品抵扣比例,意义同上。|-|
+|assistant_deduct_radio|float|assistant_deduct_radio|助教抵扣比例,意义同上。|-|
+|table_service_deduct_radio|float|table_service_deduct_radio|台费服务金抵扣比例。|-|
+|goods_service_deduct_radio|float|goods_service_deduct_radio|商品服务金抵扣比例。|-|
+|assistant_service_deduct_radio|float|assistant_service_deduct_radio|助教服务金抵扣比例。|-|
+|assistant_reward_deduct_radio|float|assistant_reward_deduct_radio|助教奖励金抵扣比例(未启用)。|-|
+|coupon_deduct_radio|float|coupon_deduct_radio|券抵扣比例(未启用)。|-|
+|card_settle_deduct|float|cardSettleDeduct|结算时统一扣卡金额配置(当前为 0.0,未使用)。|-|
+|table_card_deduct|float|tableCardDeduct|台费扣卡金额配置,当前 0.0。|-|
+|table_service_card_deduct|float|tableServiceCardDeduct|台费服务金扣卡金额配置。|-|
+|goods_card_deduct|float|goodsCarDeduct|商品扣卡金额配置。|-|
+|goods_service_card_deduct|float|goodsServiceCardDeduct|商品服务金扣卡金额配置。|-|
+|assistant_card_deduct|float|assistantCardDeduct|助教扣卡金额配置。|-|
+|assistant_service_card_deduct|float|assistantServiceCardDeduct|助教服务金扣卡金额配置。|-|
+|assistant_reward_card_deduct|float|assistantRewardCardDeduct|助教奖励金扣卡金额配置(未启用)。|-|
+|coupon_card_deduct|float|couponCardDeduct|使用券扣卡金额配置。|-|
+|delivery_fee_deduct|float|deliveryFeeDeduct|配送费扣卡金额配置(未启用)。|-|
+|table_area_id|jsonb|tableAreaId|可用台区 ID 列表,空表示不限台区。|-|
+|goods_category_id|jsonb|goodsCategoryId|可用商品分类 ID 列表,空表示不限制商品类别。|-|
+|pd_assistant_level|jsonb|pdAssistantLevel|允许的陪打助教等级列表,空表示不限。|-|
+|cx_assistant_level|jsonb|cxAssistantLevel|允许的促销助教等级列表,空表示不限。|-|
+
+
+**dim_member_card_account 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|member_card_id|主键|-|-|主键字段|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID。|
+|register_site_id|外键|dim_site|site_id|开卡门店 ID。|
+|tenant_member_id|外键|dim_member|member_id|会员档案中的会员 ID。|
+|system_member_id|外键|dim_system_member|system_member_id|全局会员 ID。|
+|card_type_id|外键|dim_card_type|card_type_id|卡种 ID。|
+------------------------------------------------------------
+### 租户级商品档案
+来自 tenant_goods_master。每行代表一款商品标准定义。
+
+**dim_tenant_goods**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|tenant_goods_id|BIGINT|id|租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。|主键|
+|tenant_id|BIGINT|tenant_id|租户/品牌 ID,用于区分不同商户。当前样本中全表同一值,但模型上应作为维表外键,用于关联租户维度。|外键|
+|supplier_id|BIGINT|supplier_id|供应商 ID,用于关联供应商档案维度。当前样本全部为 0,说明门店尚未维护供应商信息或导出视图未包含真实供应商关联,但字段含义明确。|外键|
+|category_name|VARCHAR(64)|categoryName|商品一级分类名称(可读名称),例如:零食、饮料、香烟、雪糕、小吃、酒水、面、槟榔等。真实分类关联通过 goods_category_id 与 goods_second_category_id 实现,此字段主要用于展示和直观分析。|-|
+|goods_category_id|BIGINT|goods_category_id|商品一级分类 ID。与分类维表(例如 dim_goods_category)关联,构成商品分类的第一层。一个 goods_category_id 对应一个 category_name。|外键|
+|goods_second_category_id|BIGINT|goods_second_category_id|商品二级分类 ID。与分类维表的二级节点关联,用于更细粒度的品类统计。取值数目约十四种,每个值属于某个一级分类之下。|外键|
+|goods_name|VARCHAR(128)|goods_name|商品名称(前台展示名),如 “东方树叶”“红烧牛肉面”“百威 235 毫升”等。当前样本中基本唯一。作为用户认知的主显示名称,用于报表、前台展示、小票打印。|-|
+|goods_number|VARCHAR(64)|goods_number|商品内部编号或自定义货号。当前样本中各记录不重复,如 “1”“2”“10”“11” 等。可用于与其他系统对接或人工查找,有一定对账和排错价值。|-|
+|unit|VARCHAR(16)|unit|商品计量单位,例如:瓶、包、个、份、根、盒、杯、桶、盘、支等。用于解释数量含义,是销售数量与库存数量的度量单位。|-|
+|market_price|DECIMAL(18,2)|market_price|商品标价或标准销售单价。例如 2、5、6、8、10、12、15、18、20、28 元。POS 默认销售价格,结算时的基础金额字段。|-|
+|goods_state|INT|goods_state|商品状态枚举。当前样本全部为 1,推测含义为“正常”“已上架”或“有效”。其他值(数据中未出现)通常表示下架、停用或草稿状态。用于控制商品是否可销售。|-|
+|create_time|DATETIME|create_time|商品档案创建时间,格式为 “YYYY-MM-DD HH:MM:SS”。每条记录唯一。用于增量抽取和审计,也可用于分析商品生命周期。|-|
+|update_time|DATETIME|update_time|商品档案最近一次修改时间,可为空(表示自创建后未修改)。用于增量同步、变化跟踪和审计分析。|-|
+|is_delete|INT|is_delete|逻辑删除标志。枚举:0 表示未删除(有效商品);1 表示已逻辑删除(在前台不再展示)。当前样本全部为 0。用于软删除控制和历史数据保留。|-|
+
+
+**dim_tenant_goods_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|tenant_goods_id|BIGINT|id|租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。|主键|
+|remark_name|VARCHAR(128)|remark_name|商品备注名或别名,目前样本中均为空。设计用途为简写名、特殊展示名或内部备注,在当前门店尚未启用。|-|
+|pinyin_initial|VARCHAR(128)|pinyin_initial|商品拼音首字母或助记码,用于前台按拼音检索,如 “DFSY,DFSX”“HSNRM,GSNRM”“SP” 等。主要为操作便利,对经营分析影响较小。|-|
+|goods_cover|VARCHAR(512)|goods_cover|商品封面图片 URL,用于前端展示商品图片。多个商品可能共用同一图片。对经营和结算逻辑无直接影响。|-|
+|goods_bar_code|VARCHAR(64)|goods_bar_code|商品条码(如 EAN 码)。当前样本全部为空。含义明确但尚未使用,未来可用于扫码收银或与第三方商品库对接。|-|
+|commodity_code|VARCHAR(64)|commodity_code|对外商品编码或系列编码,用于与外部系统或其他内部模块对接。例如 “10000”“100000”“10000028”等。一个编码在多条商品上复用,说明它不是主键而是“系列标识”或“外部编码”。具体业务含义依赖上游系统定义。|-|
+|commodity_code_list|VARCHAR(256)|commodityCode|商品编码列表的序列化形式,对应源 JSON 的数组字段(当前每条记录仅一个元素)。设计上支持 “一个商品多个编码” 场景,目前仅为 commodity_code 的冗余表现形式。|-|
+|min_discount_price|DECIMAL(18,2)|min_discount_price|商品可售最低价(底价)。部分记录为 0.00,表示未设置底价或沿用系统默认规则。用于限制打折或手动改价的下限,防止亏损销售。|-|
+|cost_price|DECIMAL(18,2)|cost_price|商品成本价,当前大多数为 0.00,仅少数录入 2.0、2.5、3.0 等。用于成本核算与毛利分析。虽当前门店未完整维护,但字段含义清晰,属于成本分析必备结构。|-|
+|cost_price_type|INT|cost_price_type|成本价格类型枚举,用于标识成本价的来源或计算方式。已知取值:1 和 2。常见推测:1 表示手工录入成本;2 表示按最近进货价或加权平均价生成。具体含义需结合系统枚举字典确认。|-|
+|able_discount|INT|able_discount|是否允许该商品参与折扣的标志。已知取值:1。按命名推断枚举约定为:1 表示允许参与打折;0 表示不允许参与打折(当前样本未出现)。配合活动、整单折扣等控制哪些商品可享优惠。|-|
+|sale_channel|INT|sale_channel|销售渠道类型枚举。当前样本全部为 1,推测为“线下门店正常销售渠道”。理论上可扩展为不同渠道值,例如外卖、小程序、电商等,用于渠道维度分析。具体枚举说明依赖系统配置。|-|
+|is_warehousing|INT|is_warehousing|是否纳入库存管理的标志。已知取值:1,表示纳入库存管理;0 则表示不纳入库存管理(虚拟商品等,当前未出现)。本门店所有商品均启用库存管理。|-|
+|is_in_site|boolean|isInSite|是否在当前门店启用或上架。当前样本全部为 false。由于该文件是租户级商品档案视图,且 isInSite 全为 false,该字段在本视图的实际含义存在不确定性,可能仅在门店级商品表中才有明确业务意义。|-|
+|able_site_transfer|INT|able_site_transfer|是否允许门店间调拨或门店级操作的枚举。已知取值:2 为绝大多数,0 为少数一条。按命名推测大致含义为:2 表示允许调拨或默认允许;0 表示禁止调拨。实际枚举定义需查阅系统配置,当前无法完全确定具体业务规则。|-|
+|common_sale_royalty|INT|common_sale_royalty|普通销售提成或佣金配置字段,单位和含义需结合上游系统(可能为金额或比例)。当前样本全部为 0,说明未启用商品级提成配置。|-|
+|point_sale_royalty|INT|point_sale_royalty|积分销售相关的提成或赠送规则配置字段。当前样本全部为 0,同样未启用该功能。具体数值含义(百分比或固定值)需结合系统定义。|-|
+|out_goods_id|BIGINT|out_goods_id|外部系统商品 ID,用于对接第三方平台或统一商品库时作为映射主键。目前样本全部为 0,说明尚未配置外部商品映射,具体对接规则依赖上游系统。|-|
+
+
+**dim_tenant_goods 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|tenant_goods_id|主键|-|-|主键字段|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID。|
+|supplier_id|外键|dim_supplier|supplier_id|供应商 ID。|
+|goods_category_id|外键|dim_goods_category|category_id|商品一级分类 ID。|
+|goods_second_category_id|外键|dim_goods_category|category_id|商品二级分类 ID。|
+
+
+
+------------------------------------------------------------
+
+### 门店级商品档案
+来自 store_goods_master.json。每行代表门店自定义的商品 SKU,包括售价和折扣。关联到 dim_tenant_goods 和分类维度。
+
+**dim_store_goods**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|site_goods_id|bigint|id|门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。|主键|
+|tenant_id|bigint|tenant_id|租户/品牌 ID,同一品牌下多个门店共享,用于跨门店汇总分析。|外键|
+|site_id|bigint|site_id|门店 ID,对应门店维度表主键。|外键|
+|tenant_goods_id|bigint|tenant_goods_id|租户级(品牌级)商品 ID,用于关联 dim_tenant_goods,实现跨门店统一商品档案。|外键|
+|goods_name|varchar|goods_name|商品名称,例如“合味道泡面”“地道肠”“茶位费”。|-|
+|goods_category_id|bigint|goods_category_id|商品一级分类 ID,对应商品分类维表主键,与 category_level1_name 一一对应。|外键|
+|goods_second_category_id|bigint|goods_second_category_id|商品二级分类 ID,其父分类为 goods_category_id。|外键|
+|category_level1_name|varchar|oneCategoryName|一级分类名称,如“零食”“酒水”“服务费”,用于报表维度展示。|-|
+|category_level2_name|varchar|twoCategoryName|二级分类名称,如“面”“洋酒”“纸巾”,用于更细粒度分类分析。|-|
+|batch_stock_qty|int|batch_stock_quantity|当前成本批次的库存数量,用于按 cost_price 估算库存价值。|-|
+|sale_qty|int|sale_num|截至导出时的销售数量(件),当前数据中与 total_sales_qty 相同。|-|
+|total_sales_qty|int|total_sales|累计销售数量;当前导出周期下与 sale_qty 一致,为历史全量口径。|-|
+|sale_price|decimal(18,2)|sale_price|商品标准销售价(挂牌价),单位为元。实际结算可能有折扣或券抵扣。|-|
+|created_at|datetime|create_time|门店商品档案创建时间(在门店建立该商品档案时的时间点)。|-|
+|updated_at|datetime|update_time|最近一次修改商品档案的时间(包括价格调整、状态变更等)。|-|
+|avg_monthly_sales|decimal(18,4)|average_monthly_sales|平均月销量(件/月),由某个统计周期内销售数据折算而来,用于补货和品类管理分析。|-|
+|goods_state|tinyint|goods_state|商品基础状态枚举:1=正常状态(主流值),2=特殊状态(如新建未完全启用或停售但未彻底下架,通常伴随 stock=0、days_on_shelf=0)。|-|
+|enable_status|tinyint|enable_status|档案启用状态:1=启用;2=停用(推测,样本中未出现);控制商品档案是否参与业务处理。|-|
+|send_state|tinyint|send_state|销售端可售状态:1=可销售/可下单;其他值可能代表停售或仅内部使用(当前样本全部为 1)。|-|
+|is_deleted|tinyint|is_delete|逻辑删除标志:0=未删除(有效档案);1=已删除(逻辑删除,不再参与业务但保留历史引用)。|-|
+
+
+**dim_store_goods_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|site_goods_id|bigint|id|门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。|主键|
+|site_name|varchar|siteName|门店名称,例如“朗朗桌球”,是对 site_id 的冗余展示,方便直接阅读。|-|
+|unit|varchar|unit|销售计量单位,如“包”“瓶”“个”“份”“杯”等。|-|
+|goods_barcode|varchar|goods_bar_code|商品条形码,用于扫码销售;当前样本多为空。|-|
+|goods_cover_url|varchar|goods_cover|商品图片 URL,用于前端展示商品图片。|-|
+|pinyin_initial|varchar|pinyin_initial|商品名称拼音首字母缩写,有时多个别名用逗号分隔,用于按字母快速检索和排序。|-|
+|stock_qty|int|stock|当前主单位可用库存数量,以 unit 为单位。|-|
+|stock_secondary_qty|int|stock_A|副单位库存数量;若商品存在双单位(如箱/瓶),用于记录副单位库存;当前门店未启用双单位库存,样本中为 0。|-|
+|safety_stock_qty|int|safe_stock|安全库存阈值,低于该值时系统可提示补货;当前门店尚未配置,样本中为 0。|-|
+|cost_price|decimal(18,4)|cost_price|商品单件成本价,单位元;部分商品为 0,表示未录入或由其它模块结转成本。|-|
+|cost_price_type|tinyint|cost_price_type|成本类型枚举:1=固定成本价(按 cost_price 计),2=动态成本价(按采购单等方式结转,当前多数仍为暂估)。|-|
+|provisional_total_cost|decimal(18,2)|provisional_total_cost|当前库存暂估总成本,单位元;通常约等于 batch_stock_qty × cost_price。|-|
+|total_purchase_cost|decimal(18,2)|total_purchase_cost|当前库存总采购成本,单位元;当前样本中与 provisional_total_cost 相等,为后续精算成本预留。|-|
+|min_discount_price|decimal(18,2)|min_discount_price|最低允许成交价(限价),单位元;收银改价时需保证成交价 ≥ 此值,为 0 时表示未设置限价或由其它规则控制。|-|
+|is_discountable|tinyint|able_discount|是否允许参与折扣的标志:1=允许参与折扣;0=不参与任何折扣策略。当前样本全部为 1。|-|
+|days_on_shelf|int|days_available|商品在架天数或可售天数,大致等于当前时间减去首次上架时间;0 通常表示刚建档或刚启用。|-|
+|audit_status|tinyint|audit_status|审核状态枚举:2=审核通过(当前唯一值);其他值可能代表待提交、待审核、审核不通过等。|-|
+|sale_channel|tinyint|sale_channel|销售渠道枚举:当前样本全部为 1 表示线下门店渠道;其他值可用于区分外卖、线上商城等渠道。|-|
+|is_warehousing|tinyint|is_warehousing|是否纳入库存管理:1=参与库存管理(有出入库流水);0 或其他值可能表示不计库存(样本中全部为 1)。|-|
+|freeze_status|tinyint|freeze|冻结状态:0=未冻结;非 0 可能表示锁定库存或禁止出库,具体业务规则需系统确认。|-|
+|forbid_sell_status|tinyint|forbid_sell_status|禁止销售状态:1=未禁止,允许销售;2=被禁止销售,即使上架也不能卖(含义基于命名和行业惯例推测)。|-|
+|able_site_transfer|tinyint|able_site_transfer|是否允许跨门店调拨或跨站点共享库存:2=不允许跨店调拨(当前主流值);0=未配置(个别记录),含义为是否参与跨店调拨功能。|-|
+|custom_label_type|tinyint|custom_label_type|自定义标签类型(基于字段名和取值推测):2=使用自定义标签;1 可能表示使用系统默认标签。具体影响哪些标签功能需业务确认。|-|
+|option_required|tinyint|option_required|是否需要额外选项或规格(基于字段名和取值推测):1=不需要额外选项,按单规格销售;其他值可能表示必须选择配料或口味。当前样本全部为 1。|-|
+|remark|varchar|remark|商品备注,可填写口味说明、供应商信息、注意事项等;当前样本全部为空。|-|
+|sort_order|int|sort|前端展示排序权重,控制商品在列表中的显示顺序,具体规则(数值越大还是越小排前)由业务配置决定。|-|
+
+
+**dim_store_goods 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|site_goods_id|主键|-|-|主键字段|
+|tenant_id|外键|dim_tenant|tenant_id|租户 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|tenant_goods_id|外键|dim_tenant_goods|tenant_goods_id|租户级商品 ID。|
+|goods_category_id|外键|dim_goods_category|category_id|商品一级分类 ID。|
+|goods_second_category_id|外键|dim_goods_category|category_id|商品二级分类 ID。|
+
+
+------------------------------------------------------------
+
+### 商品分类索引树
+来自 stock_goods_category_tree.json。要点与建模建议:
+- 仅两级:根节点 pid=0,子节点 pid=父 id,无孙节点;categoryBoxes 只是子节点数组。
+- 原始 JSON 分页重复两次,去重后只有 26 个节点(9 个根 + 17 个子)。
+- DWD 存储:打平一行一节点,保留 id/pid/category_name/alias_name/tenant_goods_business_id/sort/is_warehousing 等字段,categoryBoxes 不必存;以 id 为主键,pid 作为同表父级外键。
+
+**dim_goods_category**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|category_id|bigint|id|分类节点主键。来自分类树节点的 id,在整个商品分类维度内唯一。用于在事实表中作为商品分类外键引用。|主键|
+|tenant_id|bigint|tenant_id|租户 ID(商户/品牌 ID)。当前所有节点取值相同,表示同一个租户下的分类树。事实表可通过该字段与租户维度或门店维度间接关联。|外键|
+|category_name|varchar(50)|category_name|分类名称。一级大类示例:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。二级子类示例:槟榔、皮头、球杆、其他、饮料、酒水、茶水、咖啡、加料、洋酒、果盘、面、小吃等。用于前台展示和报表按细分类统计。|-|
+|alias_name|varchar(50)|alias_name|分类别名。当前样例数据全部为空字符串,预留给业务方做简称或别名展示。对现阶段经营分析无影响。|-|
+|parent_category_id|bigint|pid|父级分类 ID。根节点取值为 0,表示没有父分类;子节点取值为父分类的 id。与 category_id 共同形成树形层级关系。|外键|
+|business_name|varchar(50)|business_name|业务大类名称。将多个细分类归入同一业务线。观测值与一级大类相同:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。子类的 business_name 继承所属根节点的大类名称。用于按业务线汇总库存和销售。|-|
+|tenant_goods_business_id|bigint|tenant_goods_business_id|业务大类 ID。每个 business_name 对应唯一一个 tenant_goods_business_id,根节点和其下所有子节点共享同一取值。例如“酒水”大类及其子类饮料、茶水、咖啡、加料、洋酒拥有相同的业务 ID。可作为外键连接“业务线维度表”。|外键|
+|category_level|tinyint|由 pid 推导|分类层级:1 表示一级大类(pid = 0),2 表示二级子类(pid ≠ 0)。方便在报表中区分大类与子类进行分组和展示层级控制。|-|
+|is_leaf|tinyint|由 categoryBoxes 推导|是否叶子节点:1 表示叶子分类(categoryBoxes 为空列表),0 表示非叶子分类(存在子分类)。当前样例数据中,一级大类是非叶子节点,二级分类是叶子节点。用于树状导航或限制只能在叶子分类建商品。|-|
+|open_salesman|tinyint|open_salesman|营业员开关控制。枚举含义根据业务系统定义,一般设计为:1 表示启用营业员/导购相关功能,2 表示关闭或不启用。当前样例所有分类取值为 2,说明这一套分类在库存模块中统一未启用营业员逻辑。对目前的经营分析影响较小。|-|
+|sort_order|int|sort|分类排序序号。来自 sort 字段,用于前端展示顺序控制,数值越小越靠前。当前大部分分类为 0,仅少数为 1,说明排序配置较为粗略。对指标统计无实质影响。|-|
+|is_warehousing|tinyint|is_warehousing|是否参与库存管理。枚举:1 表示参与库存管理,0 表示不参与(如服务类商品、手工费用)。当前文件中所有分类取值为 1,表示这一份分类树只包含“走库存”的商品分类。可在库存报表中用作过滤条件。|-|
+
+
+
+------------------------------------------------------------
+
+### 团购套餐定义
+来自 group_buy_packages。每行代表一种团购套餐及其使用规则。
+
+**dim_groupbuy_package**
+|数据库字段名|字段类型|来源字段|说明(含枚举与取值说明)|角色|
+|---|---|---|---|---|
+|groupbuy_package_id|bigint|id|门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。|主键|
+|tenant_id|bigint|tenant_id|租户(品牌/商户)ID。本数据集中全表相同,表示同一品牌。|外键(指向租户维)|
+|site_id|bigint|site_id|门店 ID,本表所有记录属于同一门店。与其他 JSON 的 site_id 一致。|外键(指向门店维)|
+|package_name|varchar(200)|package_name|团购套餐名称,用于前台展示及核销界面,例如“早场特惠一小时”“KTV欢唱四小时”等。|-|
+|package_template_id|bigint|package_id|上层套餐 ID 或总部/系统级套餐 ID。多个 groupbuy_package_id 可能共享同一个 package_template_id,表示同一业务套餐在不同门店或不同版本下的配置。|外键(指向套餐模板维,后续可建)|
+|selling_price|decimal(10,2)|selling_price|团购售卖价,面向顾客在外部平台的成交价格。当前样本全部为 0,实际平台售价可能在外部系统,不在本地落地。|-|
+|coupon_face_value|decimal(10,2)|coupon_money|券面值或内部结算面值。表示此套餐在门店侧可以抵扣的金额,用于验券或套餐流水时记账。例如“早场特惠一小时”可配置为 40.00,“KTV欢唱四小时”可配置为 200.00。当前样本为 0 但字段设计上非常关键。|-|
+|duration_seconds|int|duration|套餐包含的时长,单位为秒。常见取值:3600 表示 1 小时,7200 表示 2 小时,14400 表示 4 小时。核销时可用于换算可用台费时长。|-|
+|start_time|datetime|start_time|套餐整体生效开始时间。例如“2025-07-20 00:00:00”。通常从某日零点开始。|-|
+|end_time|datetime|end_time|套餐整体生效结束时间。在该时间点之后不可使用。极大日期(如 9999-12-31 23:59:59)可视为长期有效。|-|
+|table_area_name|varchar(100)|table_area_name|套餐适用的门店台区名称,例如“A区中八”“B区中八”“斯诺克”“包厢”“KTV”等。主要用于展示和过滤,配合区域 ID 列实现人类可读的说明。|-|
+|is_enabled|int|is_enabled|启用状态枚举。1 表示启用或上架;2 表示停用或下架。侧重表示“配置是否上架”,与 effective_status 区分。|-|
+|is_deleted|int|is_delete|逻辑删除标志。0 表示正常;1 表示逻辑删除(数据仍保留但不再使用)。当前样本全部为 0。|-|
+|create_time|datetime|create_time|套餐配置在系统中的创建时间,用于审计和版本追踪。|-|
+|tenant_table_area_id_list|varchar(512)|tenant_table_area_id_list|租户级台区分组 ID 列表。当前每条记录为一个大整数(例如 2791960001957765)字符串,表示“台区分组”主键。系统通过此分组再关联到具体多个台区。|外键(指向台区分组维,后续可建)|
+|card_type_ids|varchar(255)|card_type_ids|允许使用本套餐的会员卡类型 ID 列表。当前样本统一为字符串“0”,表示未限制卡种,任意顾客或任意会员卡都可使用。若未来启用,将以分隔的 ID 列表形式记录限定卡种。|外键(潜在指向卡种维)|
+
+
+
+**dim_groupbuy_package_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举与取值说明)|角色|
+|---|---|---|---|---|
+|groupbuy_package_id|bigint|id|门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。|主键|
+|site_name|varchar(100)|site_name|门店名称,当前均为“朗朗桌球”。属于冗余展示字段,可用于报表标题。|-|
+|usable_count|int|usable_count|可使用次数上限。当前全部为 9999999,用作“无限次使用”的哨兵值。若未来限制次数,只需配置为具体次数。|-|
+|date_type|int|date_type|日期限制类型枚举。当前样本全部为 1。推测常见含义:1 表示“全部日期可用”;其他值可用于区分工作日、周末或指定日期等模式。|-|
+|usable_range|varchar(255)|usable_range|日期范围说明的文本,例如“周一至周五”等。当前全部为空字符串,实际规则由 date_type 与时间段字段控制。|-|
+|date_info|varchar(255)|date_info|更细粒度的日期信息,可能用于存储具体日期列表或节假日规则,形式可能是编码或 JSON 字符串。当前几乎全部为空,仅有极少记录为“0”。|-|
+|start_clock|varchar(16)|start_clock|每日可用时间段的起始时间(第一段),字符串格式 HH:MM:SS,例如“10:00:00”“00:00:00”。与 end_clock 组合定义日内时段。|-|
+|end_clock|varchar(16)|end_clock|每日可用时间段的结束时间(第一段),字符串格式 HH:MM:SS。与 start_clock 共同描述第一段可用时段。|-|
+|add_start_clock|varchar(16)|add_start_clock|附加可用时段的起始时间(第二段),格式 HH:MM:SS。当前样本常见值为“00:00:00”或“10:00:00”。用于配置早场加夜场等双时段场景。|-|
+|add_end_clock|varchar(16)|add_end_clock|附加可用时段的结束时间(第二段)。常见值如“1.00:00:00”“18:00:00”“23:59:00”。其中“1.00:00:00”表示跨至次日零点,用于表示“可用到第二天凌晨”的场景。|-|
+|area_tag_type|int|area_tag_type|区域标记类型枚举。当前样本全部为 1。推测 1 表示“按台区标签限制”(如 A 区、B 区、中八、斯诺克、包厢、KTV 等)。其他取值可能对应按具体台桌或其它规则限用。|-|
+|table_area_id|bigint|table_area_id|单一台区 ID。当前样本全部为 0。原始设计用于限定只能在一个具体区域使用,但由于已引入多选逻辑,实际使用已迁移到 tenant_table_area_id_list。|-|
+|tenant_table_area_id|bigint|tenant_table_area_id|租户级台区 ID,单值版本。当前样本全部为 0。与 table_area_id 类似,已被多选列表字段取代。|-|
+|table_area_id_list|varchar(512)|table_area_id_list|门店级台区 ID 列表。当前样本全部为空字符串。根据命名推测原本用于存储多个 table_area_id,实际实现已转向租户维度列表字段。|-|
+|group_type|int|group_type|团购类型枚举。当前样本全部为 1。推测 1 表示“计时类/台费类套餐”。其他取值可能用于商品类套餐、代金券类等,需结合系统配置进一步确认。|-|
+|system_group_type|int|system_group_type|系统级团购类型枚举。当前样本全部为 1。推测 1 表示“券码类团购”,即通过券码核销。其他取值可能为卡内套餐、内部套餐等,具体含义有待业务确认。|-|
+|package_type|int|type|内部业务子类型枚举。样本中取值有 1 与 2,各占比不同。具体含义不明,可能区分不同产品线或套餐来源,例如“平台合作套餐”与“自定义套餐”等,需要参考业务文档。|-|
+|effective_status|int|effective_status|当前有效状态枚举,由系统根据时间及配置动态计算。观测值:1 表示当前有效,可正常核销;3 表示失效或已过期(即使 is_enabled 仍为 1,也不可使用)。可用于分析时过滤失效套餐。|-|
+|max_selectable_categories|int|max_selectable_categories|最大可选择分类数或子项数,具体含义未在样本和说明中体现,当前值全部为 0。可能用于“组合型套餐”中限制可选项目数量。|-|
+|creator_name|varchar(100)|creator_name|创建人名称,例如“店长:郑丽珊”。主要用于审计追踪和后台展示。|-|
+
+
+
+**dim_groupbuy_package 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|groupbuy_package_id|主键|-|-|主键字段|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|package_template_id|外键|dim_groupbuy_package_template|package_template_id|总部/模板套餐主键(预留外键)。|
+|tenant_table_area_id_list|外键|dim_table_area_group|tenant_table_area_group_id|多值字段,关联租户级台区分组。|
+|card_type_ids|外键|dim_card_type|card_type_id|多值字段,限定可用卡种。|
+
+
+
+------------------------------------------------------------
+------------------------------------------------------------
+事实表(DWD)
+以下事实表均以“业务事件”为粒度,不做聚合。字段来源包括原始 JSON(或ODS) 中的明细数组以及对象属性。时间单位均统一为秒,并保留原始字段以备检查。金额按照源系统保持符号规则,不做符号转换。
+
+
+### 结账记录
+来自 settlement_records的内层 settleList 对象,每行代表一次结账。该表在业务上是其他明细事实表的汇总头,用于串联台费、商品、助教、券等明细。
+
+**dwd_settlement_head**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|业务重要性|
+|---|---|---|---|---|---|
+|order_settle_id|BIGINT|settleList.id|结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。|主键| |
+|tenant_id|BIGINT|settleList.tenantId|租户/商户 ID(品牌维度),与各业务 JSON 中的 tenantId 一致。|外键|重要|
+|site_id|BIGINT|settleList.siteId|门店 ID,用于关联门店维表 dim_site。|外键|重要|
+|site_name|VARCHAR(100)|settleList.siteName|门店名称快照,冗余展示字段,推荐通过 site_id 关联维表获取标准名称。|-|重要|
+|table_id|BIGINT|settleList.tableId|结账关联的桌台 ID,对应台桌维表 dim_site_table 的主键。|外键|重要|
+|settle_name|VARCHAR(100)|settleList.settleName|结账对象名称,一般为 “区域 + 桌号”,如 “A区 A17”,便于报表展示。|-|重要|
+|order_trade_no|BIGINT|settleList.settleRelateId|交易号 / 订单流水号,与台费、助教等明细中的 order_trade_no 一致,用于按“交易维度”串联各业务明细。|-|重要|
+|create_time|DATETIME|settleList.createTime|结账创建时间(收银端点击“确认结账”的时间),格式:YYYY-MM-DD HH:MM:SS。|-|重要|
+|pay_time|DATETIME|settleList.payTime|实际支付完成时间,通常晚于 create_time,用于资金结算及对账分析。|-|重要|
+|settle_type|TINYINT|settleList.settleType|结账类型枚举。样本中主要有:1=正常结账;3=特殊类型结账(如挂账、补单、调整单等,具体需业务确认)。|-|重要|
+|revoke_order_id|BIGINT|settleList.revokeOrderId|若当前记录属于撤销链路,记录对应的撤销单或原单的结账 ID,形成自关联关系。样本中为 0。|外键|重要|
+|member_id|BIGINT|settleList.memberId|会员主键 ID,一般对应租户维度的会员 ID,用于关联 dim_member。|外键|重要|
+|member_name|VARCHAR(100)|settleList.memberName|会员姓名快照,冗余展示字段;当前样本多为空,推荐通过关联会员维表获取标准姓名。|-|重要|
+|member_phone|VARCHAR(50)|settleList.memberPhone|会员手机号快照,冗余展示字段,通常通过会员维表获取更可靠。|-|重要|
+|member_card_account_id|BIGINT|settleList.tenantMemberCardId|会员卡账户 ID,对应 dim_member_card_account 主键;当前样本多为 0,但结构上是“结账 → 具体卡账户”的外键。|外键|重要|
+|member_card_type_name|VARCHAR(100)|settleList.memberCardTypeName|会员卡类型名称快照,如“储值卡”“次卡”等,便于前端展示和报表查看。|-|重要|
+|is_bind_member|TINYINT(1)|settleList.isBindMember|本单是否绑定会员。0=否(散客);1=是(存在 member_id)。样本中多为 0。|-|重要|
+|member_discount_amount|DECIMAL(18,2)|settleList.memberDiscountAmount|会员折扣产生的优惠金额(元),例如会员卡折扣减免的台费/商品金额,参与整单优惠拆分。|-|重要|
+|consume_money|DECIMAL(18,2)|settleList.consumeMoney|本次结账消费总额(原价小计),约等于台费 + 商品 + 助教 + 服务等项目原价金额之和,未扣除任何优惠。|-|重要|
+|table_charge_money|DECIMAL(18,2)|settleList.tableChargeMoney|本单台费(桌台计费部分)的金额(原价侧)。|-|重要|
+|goods_money|DECIMAL(18,2)|settleList.goodsMoney|本单商品销售原价金额,对应酒水、小吃等商品类消费。|-|重要|
+|real_goods_money|DECIMAL(18,2)|settleList.realGoodsMoney|商品实际计入金额,通常为 goods_money 扣除部分促销/折扣之后的金额。|-|重要|
+|assistant_pd_money|DECIMAL(18,2)|settleList.assistantPdMoney|助教“排钟 / 点钟 / 按时长服务”等项目的应计金额(原价侧),与助教流水中的 ledger_amount 汇总对应。|-|重要|
+|assistant_cx_money|DECIMAL(18,2)|settleList.assistantCxMoney|助教“超休”类助教项目金额(原价侧),是对助教收入的补充拆分维度,具体业务定义需结合助教模块确认。|-|重要|
+|adjust_amount|DECIMAL(18,2)|settleList.adjustAmount|手动减免,人工调价金额汇总(整单减免或特殊价格调整),通常正值表示减免额度。|-|重要|
+|pay_amount|DECIMAL(18,2)|settleList.payAmount|本单顾客“实付金额”(不含券面值这类虚拟抵扣),等于各支付渠道金额之和减去退款等调整。|-|重要|
+|balance_amount|DECIMAL(18,2)|settleList.balanceAmount|从会员储值余额账户中扣除的金额(储值卡消费部分)。|-|重要|
+|recharge_card_amount|DECIMAL(18,2)|settleList.rechargeCardAmount|充值卡支付金额(使用充值类卡片余额支付的金额),与储值/充值型卡资金来源相关。|-|重要|
+|gift_card_amount|DECIMAL(18,2)|settleList.giftCardAmount|礼品卡或代金卡支付金额。|-|重要|
+|coupon_amount|DECIMAL(18,2)|settleList.couponAmount|本单由优惠券(团购券、代金券等)实际抵扣的金额。|-|重要|
+|rounding_amount|DECIMAL(18,2)|settleList.roundingAmount|抹零 / 四舍五入产生的金额差值,例如按角、分抹零。|-|重要|
+|point_amount|DECIMAL(18,2)|settleList.pointAmount|积分相关金额或数量。根据系统配置可能表示“使用积分抵扣的金额”或“本单获得的积分折算金额”,文档未给出唯一定义。|-|重要|
+
+
+
+**dwd_settlement_head_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|业务重要性|
+|---|---|---|---|---|---|
+|order_settle_id|BIGINT|settleList.id|结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。|主键| |
+|serial_number|INT|settleList.serialNumber|结账序列号或打印序号,当前样本全部为 0,具体业务用途未在文档中明确。|-|不重要|
+|settle_status|TINYINT|settleList.settleStatus|结账状态枚举。当前样本值均为 2,表示“已结算/已完成”;其他取值及含义未在样本和文档中出现,需后续补充。|-|不重要|
+|can_be_revoked|TINYINT(1)|settleList.canBeRevoked|本单是否仍允许撤销/冲正。0=否;1=是。样本中均为 0。主要用于运维控制,分析价值有限。|-|不重要|
+|revoke_order_name|VARCHAR(100)|settleList.revokeOrderName|撤销单名称/标识,用于人工识别撤销关系;当前样本为空。|-|不重要|
+|revoke_time|DATETIME|settleList.revokeTime|撤销时间。无撤销时通常为系统默认值(如 0001-01-01 00:00:00)。|-|不重要|
+|is_first_order|TINYINT(1)|settleList.isFirst|是否首单(新客首单)标记。0=否;1=是。当前样本全部为 0,且文档中说明为“推测用途”,具体业务定义需确认。|-|不重要|
+|service_money|DECIMAL(18,2)|settleList.serviceMoney|其他服务费金额(如包间服务费等),用于与台费、商品、助教金额区分。|-|不重要|
+|cash_amount|DECIMAL(18,2)|settleList.cashAmount|现金支付金额。|-|不重要|
+|card_amount|DECIMAL(18,2)|settleList.cardAmount|刷卡类支付金额(如银行卡/信用卡等),具体包含哪些通道需结合支付模块确认。|-|不重要|
+|online_amount|DECIMAL(18,2)|settleList.onlineAmount|线上支付金额汇总(如微信、支付宝、云闪付等),不区分具体通道。|-|不重要|
+|refund_amount|DECIMAL(18,2)|settleList.refundAmount|本单涉及的退款金额(元)。普通正常结账为 0,退单或部分退款时为正数。|-|不重要|
+|prepay_money|DECIMAL(18,2)|settleList.prepayMoney|本单使用的预付金/定金金额。|-|不重要|
+|payment_method|TINYINT|settleList.paymentMethod|支付方式整体标记(枚举)。当前样本值统一为 0,具体各枚举值对应的支付方式未在文档中说明,需业务确认。|-|不重要|
+|coupon_sale_amount|DECIMAL(18,2)|settleList.couponSaleAmount|优惠券本身的售卖金额/成本金额(例如顾客为购买套餐券支付的金额),当前样本多为 0。|-|不重要|
+|all_coupon_discount|DECIMAL(18,2)|settleList.allCouponDiscount|所有券类优惠折扣的汇总金额,用于统计“券优惠总额”。|-|不重要|
+|goods_promotion_money|DECIMAL(18,2)|settleList.goodsPromotionMoney|商品促销产生的优惠金额(如满减、买赠均摊到商品部分)。|-|不重要|
+|assistant_promotion_money|DECIMAL(18,2)|settleList.assistantPromotionMoney|助教项目参与活动/促销产生的优惠金额。|-|不重要|
+|activity_discount|DECIMAL(18,2)|settleList.activityDiscount|整单活动折扣金额(如整单打折、满减活动产生的优惠),不区分具体项目类别。|-|不重要|
+|assistant_manual_discount|DECIMAL(18,2)|settleList.assistantManualDiscount|针对助教服务的人工减免金额,与一般商品/台费折扣区分开。|-|不重要|
+|point_discount_price|DECIMAL(18,2)|settleList.pointDiscountPrice|积分抵扣对应的金额(售价侧),记录因积分使用而减少的应收金额。|-|不重要|
+|point_discount_cost|DECIMAL(18,2)|settleList.pointDiscountCost|积分抵扣对应的成本金额(成本侧),用于毛利和利润分析。|-|不重要|
+|is_use_coupon|TINYINT(1)|settleList.isUseCoupon|是否使用优惠券。0=未使用;1=使用。当前样本均为 0。|-|不重要|
+|is_use_discount|TINYINT(1)|settleList.isUseDiscount|是否使用折扣(包括会员折扣或其他整单折扣)。0=未使用;1=使用。当前样本多为 0。|-|不重要|
+|is_activity|TINYINT(1)|settleList.isActivity|是否参与营销活动。0=未参与;1=参与。|-|不重要|
+|operator_name|VARCHAR(100)|settleList.operatorName|结账操作员名称快照(通常带角色前缀,如“收银员:张三”),用于报表展示。|-|不重要|
+|salesman_name|VARCHAR(100)|settleList.salesManName|营业员/业务员名称,用于业绩归属及提成分析;样本中多为空。|-|不重要|
+|order_remark|VARCHAR(255)|settleList.orderRemark|订单备注,由收银员手工填写的文字说明,如特殊情况、赠送原因等,主要用于人工复盘。|-|不重要|
+|operator_id|BIGINT|settleList.operatorId|结账操作员用户 ID,用于关联员工/账号维度(如 dim_staff)。|外键|不重要|
+|salesman_user_id|BIGINT|settleList.salesManUserId|营业员用户 ID,可关联员工维度,用于业绩分析和提成计算。|外键|不重要|
+
+**dwd_settlement_head 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|order_settle_id|主键|-|-|结账记录主键;Ex 表复用此键一一对应。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|table_id|外键|dim_table|table_id|结账关联的台桌。|
+|member_id|外键|dim_member|member_id|绑定会员。|
+|member_card_account_id|外键|dim_member_card_account|member_card_id|绑定会员卡账户。|
+|revoke_order_id|外键|dwd_settlement_head|order_settle_id|撤销链路自关联。|
+|order_trade_no|业务键|dwd_table_fee_log / dwd_store_goods_sale / dwd_assistant_service_log|order_trade_no|跨明细表的订单号,用于事实表串联。|
+
+
+
+
+
+------------------------------------------------------------
+
+### 台费流水
+来自 table_fee_transactions的 siteTableUseDetailsList,忽略siteProfile(已在dim_site实现)。粒度为一次台费使用记录(包括包厢)。该表连结订单结账头、桌台、会员等维度。
+
+**dwd_table_fee_log**
+|数据库字段名|字段类型|来源字段|说明(含枚举值、取值说明)|角色|
+|---|---|---|---|---|
+|table_fee_log_id|BIGINT|id|台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。|主键|
+|order_trade_no|BIGINT|order_trade_no|订单交易号。整笔订单的主编号,用于把同一订单下的台费、商品、助教等多种明细串联在一起。可与支付记录中的交易号对应。|外键|
+|order_settle_id|BIGINT|order_settle_id|结算单号 / 结账 ID。对应一次完整的结账操作。与 dwd_settlement_head 的主键关联。|外键|
+|order_pay_id|BIGINT|order_pay_id|订单支付记录 ID。对应支付记录中的 id 或 relate_id(视具体模型)。用于追踪这条台费最终对应哪一条支付流水。|外键|
+|tenant_id|BIGINT|tenant_id|租户 / 品牌 ID。本文件内所有记录属于同一租户。与其他表的 tenant_id 一致,用于品牌级过滤。|外键|
+|site_id|BIGINT|site_id|门店 ID。当前样本为同一门店。与嵌套的 siteProfile.id 以及其他 JSON 中的 site_id 对应,用于门店维度关联。|外键|
+|site_table_id|BIGINT|site_table_id|桌台 ID。对应“台桌基础表”的主键。用于确定具体哪一张台或包厢。|外键|
+|site_table_area_id|BIGINT|site_table_area_id|门店内“台桌区域” ID(门店视角的区域,如 A 区、B 区、斯诺克区、包厢区)。与门店内部的区域维度对应。|外键|
+|site_table_area_name|VARCHAR(64)|site_table_area_name|台桌区域名称,如 “A区”“B区”“斯诺克区”“VIP包厢” 等。主要用于报表展示和人工阅读。|无|
+|tenant_table_area_id|BIGINT|tenant_table_area_id|租户层面的台桌区域 ID。用于品牌层统一定义的区域配置(一个区域可在多门店复用)。对应租户级区域维度。|外键|
+|member_id|BIGINT|member_id|会员 ID。多数为 0 表示散客。非 0 时表示关联会员:0 表示散客或未使用会员;>0 对应会员档案中的 id。用于将台费流水关联到 dim_member。|外键|
+|ledger_name|VARCHAR(64)|ledger_name|台号名称,例如 “A1”“A2”“S1”“VIP包厢” 等。等价于桌台维表中的展示名称,冗余在流水中作为快照。|无|
+|ledger_unit_price|DECIMAL(18,2)|ledger_unit_price|台费结算时的计费单价(元/小时或元/单位时长)。与 ledger_count 配合计算原始应收台费。常见值如 48.0、58.0、68.0、88.0、98.0、116.0 等。|无|
+|ledger_count|INT|ledger_count|计费时长单位数。与 ledger_unit_price 共同决定原始应收额。可与 real_table_use_seconds 换算关系约为:时长秒数 ≈ ledger_count × 计费粒度(例如 30 分钟、60 分钟)。|无|
+|ledger_amount|DECIMAL(18,2)|ledger_amount|原始应收台费金额,按单价与计费时长计算出来的台费金额,尚未考虑会员、券、调账等各类优惠拆分。|无|
+|real_table_charge_money|DECIMAL(18,2)|real_table_charge_money|实际向顾客收取的台费金额(现金 / 实付维度),不含券方承担、会员承担和内部调账部分。若为 0,则该笔台费完全由券、会员或内部调账承担。|无|
+|coupon_promotion_amount|DECIMAL(18,2)|coupon_promotion_amount|由优惠券、活动、团购等促销承担的优惠金额,直接抵扣在台费上。常见值为与单价或整倍数相同,例如 48.0、96.0、136.0、144.0 等。若 real_table_charge_money 为 0 且该字段等于 ledger_amount,说明台费完全由促销承担。|无|
+|member_discount_amount|DECIMAL(18,2)|member_discount_amount|由会员权益产生的优惠金额,例如会员折扣、会员免费台等。若 ledger_amount = real_table_charge_money = member_discount_amount,表示这笔台费由会员权益承担,但仍作为台费收入进行记录。|无|
+|adjust_amount|DECIMAL(18,2)|adjust_amount|手动减免,调整金额 / 调账金额。用于将台费金额转移或冲减到其他项目(例如套餐、包厢统一计费)或做手工调整。若 ledger_amount 完全被 adjust_amount 抵消,则说明该笔台费被整体调出当前台费科目。|无|
+|real_table_use_seconds|INT|real_table_use_seconds|台费实际计费时长(秒)。用于计算台费单价与费率分析。内部统一以秒为单位。|无|
+|add_clock_seconds|INT|add_clock_seconds|加钟时长(秒)。在原有使用基础上追加的累计加钟时长,常见为 2400、4200 等 60 的倍数(对应 40 分钟、70 分钟等)。|无|
+|start_use_time|DATETIME|start_use_time|台开始使用时间,即实际开台时间。与 ledger_start_time 相同,表示计费起算点。|无|
+|ledger_end_time|DATETIME|ledger_end_time|台账计费结束时间。通常与 last_use_time 相差 1 秒。可理解为系统为计费进行的截断时刻。|无|
+|create_time|DATETIME|create_time|台费流水记录创建时间,通常接近结账时间。用于区分计费期间与结账时间。|无|
+|ledger_status|INT|ledger_status|台费状态。样本中全部为 1。含义:1 表示正常已结算台费。按命名推断,0 可能表示未结算,2 可能表示作废或撤销,需要结合后续数据确认。|无|
+|is_single_order|INT|is_single_order|是否独立计费单元。枚举:1 表示该记录是独立结算的桌费;0 表示非独立结算条目(可能是合并结账、转台过程中的占位记录)。is_single_order = 0 的记录通常 ledger_count 与 real_table_use_seconds 为 0。|无|
+|is_delete|INT|is_delete|逻辑删除标志。0 表示未删除(有效记录);1 表示已逻辑删除(一般不参与统计)。当前样本全部为 0。|无|
+
+
+
+**dwd_table_fee_log_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值、取值说明)|角色|
+|---|---|---|---|---|
+|table_fee_log_id|BIGINT|id|台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。|主键|
+|operator_name|VARCHAR(64)|operator_name|操作员姓名。为冗余展示字段,便于直接阅读而不必联表员工档案。|无|
+|salesman_name|VARCHAR(64)|salesman_name|营业员姓名。当前样本为空。用于需要对营业员维度做业绩统计时作为冗余展示。|无|
+|used_card_amount|DECIMAL(18,2)|used_card_amount|由储值卡、次卡等“卡内余额”直接抵扣到台费的金额。当前样本为 0,但语义明确,用于区分“卡扣款”与“现金收款”。|无|
+|service_money|DECIMAL(18,2)|service_money|服务费 / 成本 /分成金额字段,类似助教流水里的 service_money。当前样本全为 0,门店未启用该字段,未来可能用于台费附加服务费或分成计算。|无|
+|mgmt_fee|DECIMAL(18,2)|mgmt_fee|管理费字段。当前样本为 0。推测用于未来支持“台费附加管理费”功能。尚未实际启用。|无|
+|fee_total|DECIMAL(18,2)|fee_total|附加费用合计值字段。当前样本为 0。设计上用于汇总管理费、服务费等附加费用。尚未实际启用。|无|
+|ledger_start_time|DATETIME|ledger_start_time|台账计费起始时间。当前样本与 start_use_time 相同,表示计费与开台同时开始。|无|
+|last_use_time|DATETIME|last_use_time|最后使用 / 操作时间,通常略晚于 ledger_end_time。可视为客人最后一次用台或最后一次加钟/操作的时间点。|无|
+|operator_id|BIGINT|operator_id|操作员 ID。负责开台 / 结账的员工账号 ID。与员工 / 账号体系中的用户 ID 对应。|外键|
+|salesman_user_id|BIGINT|salesman_user_id|营业员用户 ID。目前样本值为 0,表示门店暂未使用此字段做提成员工归属,但语义清晰。|外键|
+|salesman_org_id|BIGINT|salesman_org_id|营业员所属机构 / 部门 ID。目前样本为 0。用于员工组织结构统计时的归属。|外键|
+
+**dwd_table_fee_log 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|table_fee_log_id|主键|-|-|主键字段;Ex 表一一对应。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|site_table_id|外键|dim_table|table_id|球台/包厢 ID。|
+|site_table_area_id|外键|dim_area|area_id|门店维度台区。|
+|tenant_table_area_id|外键|dim_table_area_group|tenant_table_area_group_id|租户级台区分组。|
+|member_id|外键|dim_member|member_id|关联会员。|
+|order_settle_id|外键|dwd_settlement_head|order_settle_id|对应结账主单。|
+|order_pay_id|外键|dwd_payment|payment_id|对应支付流水(若存在)。|
+|order_trade_no|业务键|dwd_store_goods_sale / dwd_assistant_service_log|order_trade_no|与同单的商品、助教、台费明细串联。|
+|operator_id|外键|dim_staff|staff_id|开台/结账操作员(Ex 表字段)。|
+|salesman_user_id|外键|dim_staff|staff_id|营业员(Ex 表字段)。|
+|salesman_org_id|外键|dim_org|org_id|营业员所属组织(Ex 表字段)。|
+
+------------------------------------------------------------
+
+### 台费折扣/调整
+来自 table_fee_discount_records的table_fee_discount_records.data.taiFeeAdjustInfos. 路径下字段路径。每行代表一次台费打折或减免操作。由于结构相对简单,字段说明如下:
+
+**dwd_table_fee_adjust**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|table_fee_adjust_id|bigint|id|台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。|主键|
+|order_trade_no|bigint|order_trade_no|订单交易号;与台费流水、结账记录等表中的同名字段一致,用于把本次台费调整挂到具体订单上。|外键|
+|order_settle_id|bigint|order_settle_id|结算单 / 小票 ID;与小票、结账头表中的 order_settle_id 对应,用于关联同一次结账。|外键|
+|tenant_id|bigint|tenant_id|租户 / 品牌 ID;标识该记录属于哪一个商户。|外键|
+|site_id|bigint|site_id|门店 ID;与 dim_site、其它业务事实表中的 site_id 一致。|外键|
+|table_id|bigint|site_table_id|台桌 ID;与 dim_table(site_tables_master.id)以及各类台费、助教流水中的 site_table_id 对应,标识哪一张台发生了折扣/调账。|外键|
+|table_area_id|bigint|tableProfile.site_table_area_id|门店维度的台桌区域 ID;与 dim_table 中的 site_table_area_id 对应,例如 “斯诺克区”“VIP包厢”等区域。|外键|
+|table_area_name|varchar(64)|tableProfile.site_table_area_name|台桌区域名称快照,例如 “斯诺克区”“A区”“VIP包厢”;冗余展示字段,可从 dim_table 通过 table_area_id 获取。|-|
+|tenant_table_area_id|bigint|tenant_table_area_id|租户维度的“台桌区域 ID”;同一租户下跨门店复用的区域标识,用于在租户级别统计各区域的折扣分布。|外键|
+|ledger_amount|decimal(18,2)|ledger_amount|台费调整金额;等于台费流水中对应记录的 adjust_amount。正数表示被减免/调账掉的台费金额(本批数据全部为正);是衡量台费折扣规模的核心度量。|-|
+|ledger_status|int|ledger_status|调整记录状态(枚举)。1:生效调整(当前有效的折扣/调账记录);0:失效/被覆盖的历史记录(同一订单有多次调整时,旧记录会标记为 0,仅最新一条为 1)。|-|
+|is_delete|int|is_delete|逻辑删除标记(枚举)。0:未删除(有效记录);1:已逻辑删除(后台标记删除,不再参与业务统计)。当前数据全部为 0,但字段需保留以适配长期数据。|-|
+|adjust_time|datetime|create_time|台费调整记录创建时间,即打折/调账操作被系统写入的时间戳,用于时间分析和与结账时间对比(判断是事前折扣还是事后调账)。|-|
+
+
+
+
+**dwd_table_fee_adjust_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|table_fee_adjust_id|bigint|id|台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。|主键|
+|adjust_type|int|adjust_type|调整类型(枚举)。当前数据全部为 1。取值示例:1:台费打折 / 台费减免(本门店实际使用的唯一类型);其他值:预留给台费转移、误操作恢复等其他类型(当前未出现,仅推测)。|-|
+|ledger_count|int|ledger_count|调整次数计数,本数据中恒为 1,表示“一次调整事件”;与台费流水中的 ledger_count(计时长)含义不同。|-|
+|ledger_name|varchar(128)|ledger_name|调账项目名称或打折原因名称(设计意图);当前门店所有记录值为空字符串,未实际使用。作用暂不明确,保留以备后续业务启用。|-|
+|applicant_name|varchar(64)|applicant_name|申请人姓名快照,通常包含角色前缀(如 “收银员:张三”);是 applicant_id 的冗余展示字段,实际名称应以员工维表为准。|-|
+|operator_name|varchar(64)|operator_name|操作员姓名快照;与 operator_id 对应的姓名冗余字段。|-|
+|applicant_id|bigint|applicant_id|申请人 ID;发起本次台费折扣/调账的员工账号 ID,用于按员工维度统计折扣行为。|外键|
+|operator_id|bigint|operator_id|实际执行调账操作的操作员 ID;当前样本中与 applicant_id 相同,但模型上允许“申请人 ≠ 操作人”。|外键|
+
+
+**dwd_table_fee_adjust 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|table_fee_adjust_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|table_id|外键|dim_table|table_id|发生折扣的台桌。|
+|table_area_id|外键|dim_area|area_id|门店台区。|
+|tenant_table_area_id|外键|dim_table_area_group|tenant_table_area_group_id|租户级台区分组。|
+|order_settle_id|外键|dwd_settlement_head|order_settle_id|结账单主键。|
+|order_trade_no|业务键|dwd_table_fee_log / dwd_store_goods_sale|order_trade_no|同订单的其他明细业务键。|
+|applicant_id|外键|dim_staff|staff_id|折扣申请人(Ex 表字段)。|
+|operator_id|外键|dim_staff|staff_id|折扣执行人(Ex 表字段)。|
+
+
+------------------------------------------------------------
+
+### 商品销售明细
+来自 store_goods_sales_records的 orderGoodsLedgers。每行代表订单中的一条商品销售明细。字段较多,以下列出关键字段及其作用。
+
+**dwd_store_goods_sale**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|业务重要性|
+|---|---|---|---|---|---|
+|store_goods_sale_id|bigint|id|商品销售明细主键;每条记录代表一次订单中的一个商品行流水。|主键|-|
+|order_trade_no|bigint|order_trade_no|订单交易号(业务单号);与台费、助教、团购等表的 order_trade_no 一致,用于把同一订单下各类消费串联起来。|外键|重要|
+|order_settle_id|bigint|order_settle_id|结账记录主键 ID;连接结账记录 / 结算头事实表。|外键|重要|
+|order_pay_id|bigint|order_pay_id|支付记录 ID;连接支付流水事实表,用于还原本条销售对应的收款信息。|外键|重要|
+|order_goods_id|bigint|order_goods_id|当前版本的订单内商品明细 ID;可在订单范围内唯一定位该商品行,用于与小票明细等做行级关联。|外键|重要|
+|site_id|bigint|site_id|门店 ID(系统主键);与其它流水表中的 site_id 一致。|外键|重要|
+|tenant_id|bigint|tenant_id|租户/品牌 ID;同一品牌下多门店共享同一个 tenant_id。|外键|重要|
+|site_goods_id|bigint|site_goods_id|门店级商品 ID;连接门店商品档案 dim_store_goods,与库存变动记录中的 siteGoodsId 一致。|外键|重要|
+|tenant_goods_id|bigint|tenant_goods_id|租户级(品牌级)商品 ID;连接租户级商品档案维度表,一个 tenant_goods_id 在不同门店可对应多个 site_goods_id。|外键|重要|
+|tenant_goods_category_id|bigint|tenant_goods_category_id|租户级商品一级分类 ID;连接商品分类维度(如酒水、零食等)。|外键|重要|
+|tenant_goods_business_id|bigint|tenant_goods_business_id|租户级商品业务大类 ID(更高一层的业务分类,如“零食类”“酒水类”等)。|外键|重要|
+|site_table_id|bigint|site_table_id|球台 ID;非 0 表示该商品在某张台桌上点单,0 表示前台售卖或与台桌无关。连接台桌维度 dim_table。|外键|重要|
+|ledger_name|varchar(200)|ledger_name|销售项目名称(商品名),如“哇哈哈矿泉水”“地道肠”等;为当时销售时刻的名称快照。|-|重要|
+|ledger_group_name|varchar(100)|ledger_group_name|门店前台菜单分组名称,如“酒水”“零食”“小吃”等;与品牌统一分类是两套维度。|-|重要|
+|ledger_unit_price|decimal(18,2)|ledger_unit_price|结算单价(元/单位);本次销售实际使用的单价。|-|重要|
+|ledger_count|int|ledger_count|销售数量(以商品单位计),如 1、2、6、36 等。|-|重要|
+|ledger_amount|decimal(18,2)|ledger_amount|原始应收金额(未考虑任何折扣/抵扣),通常接近 ledger_unit_price × ledger_count。|-|重要|
+|discount_price|decimal(18,2)|discount_price|折后单价(元/单位);无折扣时等于 ledger_unit_price,有折扣时小于 ledger_unit_price。|-|重要|
+|real_goods_money|decimal(18,2)|real_goods_money|本行商品实际入账金额(已考虑折扣及其他抵扣后,实际计入营业额的金额);一定不大于 ledger_amount。|-|重要|
+|cost_money|decimal(18,2)|cost_money|本行商品对应的成本金额,用于毛利和利润分析;源自商品档案成本价及成本核算逻辑。|-|重要|
+|ledger_status|tinyint|ledger_status|销售流水状态:1=正常有效;其他数值(当前数据未出现)一般表示“待结算”“作废”等。|-|重要|
+|is_delete|tinyint|is_delete|逻辑删除标志:0=正常有效;1=已删除(仅保留历史,不再参与前端展示及统计)(本批数据全部为 0)。|-|重要|
+|create_time|datetime|create_time|销售记录创建时间,通常为结账时间或录入时间;用于时间维度分析,与订单层时间字段对齐。|-|重要|
+
+
+
+
+**dwd_store_goods_sale_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|store_goods_sale_id|bigint|id|商品销售明细主键;每条记录代表一次订单中的一个商品行流水。|主键|
+|legacy_order_goods_id|bigint|orderGoodsId|旧版订单商品明细 ID,兼容字段;当前接口已统一使用 order_goods_id,本批数据全部为 0。|-|
+|site_name|varchar(100)|siteName|门店名称,对 site_id 的冗余文本(例如“朗朗桌球”),用于展示。|-|
+|legacy_site_id|bigint|siteId|历史兼容门店 ID;当前接口统一使用 site_id,本批数据 siteId 全部为 0。|-|
+|goods_remark|varchar(255)|goods_remark|商品备注/口味说明/特殊说明;部分记录为空,部分与商品名相同。|-|
+|option_value_name|varchar(200)|option_value_name|商品选项名称(规格/口味,如大杯/小杯、不加冰等);当前门店未启用多规格,样本中全部为空。|-|
+|operator_name|varchar(100)|operator_name|操作员姓名冗余,如“收银员:郑丽珊”;用于展示,不作为关联键。|-|
+|open_salesman_flag|tinyint|openSalesman|是否启用营业员机制标志:1=启用营业员/提成体系(需指定 salesman_* 字段);2=未启用营业员体系(本批数据全部为 2)。|-|
+|salesman_user_id|bigint|salesman_user_id|营业员用户 ID(系统账号 ID);当前样本全部为 0,说明门店未启用营业员业绩统计。|外键|
+|salesman_name|varchar(100)|salesman_name|营业员姓名;当前样本全部为空字符串。|-|
+|salesman_role_id|bigint|salesman_role_id|营业员角色 ID(例如某角色代码对应“销售员”角色);当前样本全部为 0。|外键|
+|sales_man_org_id|bigint|sales_man_org_id|营业员所属组织/部门 ID;当前样本全部为 0,未启用按组织分组统计。|外键|
+|discount_money|decimal(18,2)|discount_money|本行商品的直接价格优惠金额(打折让利部分);在简单场景下满足:ledger_amount - discount_money ≈ real_goods_money(不含积分、券抵扣)。|-|
+|returns_number|int|returns_number|退货数量;当前样本全部为 0,如发生退货则记录退回的件数。|-|
+|coupon_deduct_money|decimal(18,2)|coupon_deduct_money|优惠券/团购券直接抵扣到本条商品明细上的金额;当前样本为 0,说明券更多在订单级处理。|-|
+|member_discount_amount|decimal(18,2)|member_discount_amount|由会员折扣针对本行商品产生的优惠金额;当前样本全部为 0,折扣通常体现在 discount_money 中。|-|
+|point_discount_money|decimal(18,2)|point_discount_money|由积分抵扣的金额(顾客用积分兑换的抵现金额)。|-|
+|point_discount_money_cost|decimal(18,2)|point_discount_money_cost|积分抵扣对应的成本金额(积分成本、营销费用等核算用)。|-|
+|package_coupon_id|bigint|package_coupon_id|套餐券 ID;当商品来自套餐拆分或与套餐券关联时,用于追溯对应的套餐业务(当前样本为 0)。|-|
+|order_coupon_id|bigint|order_coupon_id|订单级优惠券 ID;整单使用某张券时,可用于记录该券对本行商品的分摊关系(当前样本为 0)。|-|
+|member_coupon_id|bigint|member_coupon_id|会员券 ID(如会员专享优惠券);当前样本为 0,为会员权益预留字段。|-|
+|option_price|decimal(18,2)|option_price|商品选项(规格/加料等)的附加价格;当前门店未启用此功能,样本为 0。|-|
+|option_member_discount_money|decimal(18,2)|option_member_discount_money|由会员折扣作用在“选项价格”上的优惠金额;当前样本为 0。|-|
+|option_coupon_deduct_money|decimal(18,2)|option_coupon_deduct_money|由优惠券抵扣“选项价格”的金额;当前样本为 0。|-|
+|push_money|decimal(18,2)|push_money|本行商品对应的提成金额(营业员/业务员提成);当前样本为 0,说明提成体系未启用。|-|
+|is_single_order|tinyint|is_single_order|是否作为独立明细参与订单结算:1=作为独立明细参与订单;0=在特殊业务中可能合并为打包项目(当前样本全部为 1)。|-|
+|sales_type|tinyint|sales_type|销售类型:1=正常销售(当前样本全部为 1);常见扩展用法:2=赠品;3=内部消耗;4=盘点调整等。|-|
+|operator_id|bigint|operator_id|操作员 ID(录入本条销售的员工);与其它流水中的 operator_id 一致,可统一做员工维度分析。|外键|
+
+**dwd_store_goods_sale 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|store_goods_sale_id|主键|-|-|主键字段;Ex 表一一对应。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|site_goods_id|外键|dim_store_goods|site_goods_id|门店级商品。|
+|tenant_goods_id|外键|dim_tenant_goods|tenant_goods_id|租户级商品。|
+|tenant_goods_category_id|外键|dim_goods_category|category_id|商品一级分类。|
+|tenant_goods_business_id|外键|dim_goods_business|business_id|商品业务大类。|
+|site_table_id|外键|dim_table|table_id|点单关联的台桌。|
+|order_settle_id|外键|dwd_settlement_head|order_settle_id|结账主单。|
+|order_pay_id|外键|dwd_payment|payment_id|支付流水。|
+|order_trade_no|业务键|dwd_table_fee_log / dwd_assistant_service_log|order_trade_no|跨明细表订单号。|
+|order_goods_id|业务键|ods.order_goods|order_goods_id|订单内部商品行标识(用于软关联)。|
+|salesman_user_id|外键|dim_staff|staff_id|营业员(Ex 表字段)。|
+|salesman_role_id|外键|dim_role|role_id|营业员角色(Ex 表字段)。|
+|sales_man_org_id|外键|dim_org|org_id|营业员组织(Ex 表字段)。|
+|operator_id|外键|dim_staff|staff_id|录单操作员(Ex 表字段)。|
+
+------------------------------------------------------------
+
+### 助教服务流水
+来自 assistant_service_records的 assistant_service_records.data.orderAssistantDetails.。每行表示一次助教提供服务的记录,包括服务时长、金额、助教与会员关联等。
+
+**dwd_assistant_service_log**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|assistant_service_id|bigint|id|助教服务流水主键,系统内唯一标识一次助教服务记录。|主键|
+|order_trade_no|bigint|order_trade_no|订单交易号,用于与台费、商品、支付等同一订单下的其他明细串联。|外键|
+|order_settle_id|bigint|order_settle_id|结算单号,对应结账记录、小票中的结算主键。|外键|
+|order_pay_id|bigint|order_pay_id|支付记录主键 ID,用于关联支付流水。|外键|
+|order_assistant_id|bigint|order_assistant_id|订单中“助教项目明细”的内部 ID,一笔订单中多段助教服务时用于区分。|外键|
+|order_assistant_type|int|order_assistant_type|助教服务类型枚举:1 表示常规助教服务(如基础课);2 表示附加类助教服务(如附加课);其他值预留。|-|
+|tenant_id|bigint|tenant_id|租户/品牌 ID,用于区分商户。|外键|
+|site_id|bigint|site_id|门店 ID,对应门店维表中的门店主键。|外键|
+|site_table_id|bigint|site_table_id|球台/包厢 ID,对应台桌维表主键。|外键|
+|tenant_member_id|bigint|tenant_member_id|商户维度会员 ID,对应会员档案主键;0 表示非会员或散客。|外键|
+|system_member_id|bigint|system_member_id|系统级会员 ID,用于跨门店识别同一会员。|外键|
+|assistant_no|varchar(64)|assistantNo|助教编号/工号,如 “27”;与助教档案中的工号一致。|-|
+|nickname|varchar(64)|nickname|助教对外昵称,如“佳怡”“周周”;用于展示,不参与业务逻辑。|-|
+|site_assistant_id|bigint|site_assistant_id|门店维度助教 ID,对应助教账号维表主键。|外键|
+|user_id|bigint|user_id|助教对应的系统用户 ID,对应账号体系中的 user_id。|外键|
+|assistant_team_id|bigint|assistant_team_id|助教团队 ID,用于分组统计团队业绩。|外键|
+|person_org_id|bigint|person_org_id|助教所属人事组织/部门 ID,如“助教部”;用于组织维度分析。|外键|
+|assistant_level|int|assistant_level|助教等级编码:8=助教管理;10=初级;20=中级;30=高级;用于薪酬/评价分层。|外键|
+|level_name|varchar(64)|levelName|助教等级名称,与 assistant_level 对应,如“初级”“中级”“高级”“助教管理”。|-|
+|skill_id|bigint|skill_id|助教服务课程/技能 ID,应对应课程/技能配置表。|外键|
+|skill_name|varchar(64)|skillName|助教服务课程/技能名称,如“基础课”“附加课”。|-|
+|ledger_unit_price|decimal(10,2)|ledger_unit_price|助教服务标准单价(原价),例如按小时或按节课的标价。|-|
+|ledger_amount|decimal(10,2)|ledger_amount|按标准单价计算的应收金额,近似等于 ledger_unit_price×计费时长换算后的金额。|-|
+|projected_income|decimal(10,2)|projected_income|实际计入门店收入的金额,已经考虑会员权益、券抵扣等后的结果。|-|
+|coupon_deduct_money|decimal(10,2)|coupon_deduct_money|由优惠券、团购券等直接抵扣到本次助教服务上的金额;0 表示未使用券。|-|
+|income_seconds|int|income_seconds|计费秒数(用于计算应收收入的时间长度),通常为按分钟取整的秒数。|-|
+|real_use_seconds|int|real_use_seconds|实际服务时长(秒),真实消耗的时间,用于分析助教工作量。|-|
+|add_clock|int|add_clock|加钟秒数,在原有预约基础上临时增加的服务时间,数值为 60 的倍数。|-|
+|create_time|datetime|create_time|助教流水记录创建时间,接近下单/结算时间。|-|
+|start_use_time|datetime|start_use_time|助教实际开始服务时间,通常与 ledger_start_time 一致。|-|
+|last_use_time|datetime|last_use_time|助教最后一次服务时间,通常与 ledger_end_time 一致。|-|
+|is_delete|int|is_delete|逻辑删除标志:0 未删除;1 已逻辑删除,用于保留历史数据。|-|
+
+
+
+**dwd_assistant_service_log_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|assistant_service_id|bigint|id|助教服务流水主键,系统内唯一标识一次助教服务记录。|主键|
+|table_name|varchar(64)|tableName|球台名称,如 “A17”“S1”,与 site_table_id 冗余,用于展示。|-|
+|assistant_name|varchar(64)|assistantName|助教姓名,如“何海婷”;与助教档案中的真实姓名一致。|-|
+|ledger_name|varchar(128)|ledger_name|助教计费项目名称,如“2-佳怡”等,通常为展示用组合字段。|-|
+|ledger_group_name|varchar(128)|ledger_group_name|助教项目所属的计费分组/套餐分组名称,目前导出数据中为空,未看到实际使用场景。|-|
+|ledger_count|int|ledger_count|台账计费时长(秒),通常与 real_use_seconds 接近或相等。
+取income_seconds|-|
+|member_discount_amount|decimal(10,2)|member_discount_amount|由会员卡折扣产生的优惠金额,当前样本中为 0,但字段语义明确。|-|
+|manual_discount_amount|decimal(10,2)|manual_discount_amount|收银员手动减免金额(人工改价);当前导出数据中为 0。|-|
+|service_money|decimal(10,2)|service_money|与助教结算的金额或服务成本金额,当前数据全部为 0,具体结算规则未见启用。|-|
+|returns_clock|int|returns_clock|退钟秒数(取消加钟或提前结束退回的时间),当前样本中全部为 0,未见业务使用。|-|
+|ledger_start_time|datetime|ledger_start_time|台账计费起始时间。|-|
+|ledger_end_time|datetime|ledger_end_time|台账计费结束时间,可作为本次服务结束时间。|-|
+|ledger_status|int|ledger_status|助教流水状态:当前数据为 1,表示正常有效;其他值预留给已作废、未结算等状态。|-|
+|is_confirm|int|is_confirm|确认状态:当前样本为 2,一般含义为 1=待确认,2=已确认/已完成(含义基于字段名和现有值推断)。|-|
+|is_single_order|int|is_single_order|是否单独订单:1 表示助教服务作为单独订单结算;0 表示与其他项目合单结算。当前样本全部为 1。|-|
+|is_not_responding|int|is_not_responding|是否存在“未响应/爽约”等异常:0 表示正常;1 表示未响应或爽约(基于字段名推断,当前数据均为 0)。|-|
+|is_trash|int|is_trash|是否已废除:0 表示正常有效;1 表示已废除,与助教废除记录表(assistant_cancellation_records)对应。|-|
+|trash_applicant_id|bigint|trash_applicant_id|提出废除申请的员工 ID,用于追溯谁发起了废除操作。|外键|
+|trash_applicant_name|varchar(64)|trash_applicant_name|废除申请人姓名,仅用于展示,与 trash_applicant_id 冗余。|-|
+|trash_reason|varchar(255)|trash_reason|废除原因文案,如“顾客取消”“录入错误”,便于分析异常原因。|-|
+|salesman_user_id|bigint|salesman_user_id|营业员/销售员用户 ID,大多为 0,当前门店未明显使用此维度。|外键|
+|salesman_name|varchar(64)|salesman_name|营业员/销售员姓名,多数为空字符串。|-|
+|salesman_org_id|bigint|salesman_org_id|营业员所属组织/部门 ID,多数为 0,尚未看到实际业务使用。|外键|
+|skill_grade|int|skill_grade|课程技能评分(整数),当前样本全为 0,评价功能尚未启用。|-|
+|service_grade|int|service_grade|服务态度评分(整数),当前样本全为 0。|-|
+|composite_grade|decimal(5,2)|composite_grade|综合评分(技能+服务等加权结果),当前样本为 0。|-|
+|sum_grade|decimal(10,2)|sum_grade|累计评分总和,用于计算平均分,当前样本为 0。|-|
+|get_grade_times|int|get_grade_times|获得评价的次数,当前样本为 0。|-|
+|grade_status|int|grade_status|评价状态枚举:当前样本为 1,一般含义为“未评价/正常”,其他状态未见实际值。|-|
+|composite_grade_time|datetime|composite_grade_time|最近一次综合评分时间或评价更新时间,当前为默认时间 “0001-01-01 00:00:00”。|-|
+
+**dwd_assistant_service_log 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|assistant_service_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|site_table_id|外键|dim_table|table_id|服务所在台桌。|
+|tenant_member_id|外键|dim_member|member_id|租户内会员。|
+|system_member_id|外键|dim_system_member|system_member_id|全局会员。|
+|site_assistant_id|外键|dim_assistant|assistant_id|助教档案。|
+|user_id|外键|dim_user|user_id|系统用户。|
+|assistant_team_id|外键|dim_team|team_id|助教团队。|
+|person_org_id|外键|dim_org|org_id|人事组织。|
+|assistant_level|外键|dim_assistant_level|assistant_level|助教等级枚举。|
+|skill_id|外键|dim_skill|skill_id|课程/技能配置。|
+|order_settle_id|外键|dwd_settlement_head|order_settle_id|结账主单。|
+|order_pay_id|外键|dwd_payment|payment_id|支付流水。|
+|order_trade_no|业务键|dwd_table_fee_log / dwd_store_goods_sale|order_trade_no|跨明细表的订单号。|
+|order_assistant_id|业务键|ods.order_assistant|order_assistant_id|订单中助教明细标识。|
+|trash_applicant_id|外键|dim_staff|staff_id|废除申请人(Ex 表字段)。|
+|salesman_user_id|外键|dim_staff|staff_id|营业员(Ex 表字段)。|
+|salesman_org_id|外键|dim_org|org_id|营业员组织(Ex 表字段)。|
+
+------------------------------------------------------------
+
+### 助教废除事件
+来自 assistant_cancellation_records 的 abolitionAssistants。每行代表一次助教服务被废除的事件,无法直接与结算记录或助教流水关联,只能通过门店+台桌+助教+时间窗口软关联。
+
+**dwd_assistant_trash_event**
+|数据库字段名|字段类型|来源字段(JSON 路径)|说明(含枚举与取值)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|assistant_trash_event_id|bigint|id|助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。|主键|
+|site_id|bigint|siteId|门店 ID。与其他 JSON 中的 siteId / site_id 含义一致。用来关联 dim_site。当前样例全部为同一门店(朗朗桌球),但设计上支持多门店。|外键(指向 dim_site)|
+|table_id|bigint|tableId|台桌 ID。对应 site_tables_master.json 中的 id。用于定位哪一张球台发生了助教废除,用于后续软关联台费流水、助教流水时的重要条件。|外键(指向 dim_table)|
+|table_area_id|bigint|tableAreaId|台桌区域 ID。应与台桌维或区域维中的 area_id 一致,用于按区域统计(A 区/B 区/VIP 包厢等)。|外键(潜在指向 dim_table_area)|
+|assistant_no|varchar(32)|assistantOn|助教编号(工号/序号),如 '2'、'4'、'27' 等。与助教档案表 assistant_accounts_master.assistant_no、助教流水中的 assistantNo 一致,用于标识哪位助教。枚举:在门店内是有限编号集合,但并非硬编码含义。|外键(指向 dim_assistant)|
+|assistant_name|varchar(64)|assistantName|助教姓名/昵称,如 “泡芙”“佳怡”等。为冗余展示字段,真实姓名以助教档案为准。当前数据中与档案一致。|-|
+|charge_minutes_raw|int|pdChargeMinutes|助教被废除前“已计费时长(分钟)”的原始值。单位为分钟。示例:214、3600、10800 等。0 表示尚未发生有效计费就被废除。当前数据中存在异常大值(例如 10800),这一业务含义需结合实际规则理解,但本字段原样保留。枚举:数值型,无固定枚举。|-|
+|abolish_amount|decimal(18,2)|assistantAbolishAmount|与本次助教废除操作关联的金额,单位元。字面含义为“助教废除金额”。当前样例均为非负数,如 5.83、570.00、0.00 等。正负方向:按照 ODS/JSON 原样保留,暂不在数仓层赋予“收入/支出”的方向含义,后续在 DWS 层按业务规则解释(例如是退还顾客、扣除收益等)。|-|
+|trash_reason|varchar(255)|trashReason|废除原因的文本说明,例如可以写“顾客临时取消”“误操作”等。当前样例中全部为空字符串,说明前台并未使用该字段。但从结构上看,是一个自由文本字段,不是枚举。|-|
+|create_time|datetime|createTime|这条废除记录创建的时间,格式 YYYY-MM-DD HH:MM:SS。代表系统正式记录“废除操作”的时刻,用于和助教服务流水按时间窗口做软关联(结合 site、table、assistant 等条件)。|-|
+
+
+**dwd_assistant_trash_event_Ex**
+|数据库字段名|字段类型|来源字段(JSON 路径)|说明(含枚举与取值)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|assistant_trash_event_id|bigint|id|助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。|主键|
+|table_name|varchar(64)|tableName|台桌名称/编号,便于直观看报表,如 “C1”“B9”“VIP1”等。文案冗余自台桌维度。枚举:在门店范围内是有限集合,但不是固定编码表。|-|
+|table_area_name|varchar(64)|tableArea|台桌区域名称(中文),如 “A区”“B区”“C区”“VIP包厢”“补时长”等。展示用文本,具体层级信息由区域维表提供。|-|
+
+**dwd_assistant_trash_event 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|assistant_trash_event_id|主键|-|-|主键字段;Ex 表复用此键。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|table_id|外键|dim_table|table_id|发生废除的台桌。|
+|table_area_id|外键|dim_area|area_id|台桌区域。|
+|assistant_no|外键|dim_assistant|assistant_no|助教编号(按工号关联)。|
+
+------------------------------------------------------------
+
+### 会员余额变动
+来自 member_balance_changes.json,粒度为一次储值卡账户余额变动。此表是分析会员资金往来的核心事实表。
+
+**dwd_member_balance_change**
+|数据库字段名|字段类型|来源字段(member_balance_changes.json)|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|balance_change_id|BIGINT|id|余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。|主键|
+|tenant_id|BIGINT|tenant_id|租户/品牌 ID,在整体系统中唯一标识一家商户。当前样本中为同一值。|外键|
+|site_id|BIGINT|site_id|本次余额变动发生的门店 ID。通常对应具体门店;样本中:非 0 为“朗朗桌球”,0 代表平台级/虚拟门店场景(如活动抵用券结算)。|外键|
+|register_site_id|BIGINT|register_site_id|办卡门店 ID(卡注册门店)。与 site_id 区分:register_site_id=当初办卡门店,site_id=本次余额变动实际发生门店。当前样本中全部相同。|外键|
+|tenant_member_id|BIGINT|tenant_member_id|租户维度会员 ID(同一租户内的会员主键),用于关联会员档案。|外键|
+|system_member_id|BIGINT|system_member_id|系统全局会员 ID(跨租户统一的会员标识)。当前只有一个门店,但结构上允许同一人跨租户共享该 ID。|外键|
+|tenant_member_card_id|BIGINT|tenant_member_card_id|会员卡账户 ID(租户内唯一的一张具体卡,例如某人的储值卡/酒水卡/台费卡/活动抵用券等)。本次余额变动作用于这张卡。|外键|
+|card_type_id|BIGINT|card_type_id|卡种类型 ID。与 card_type_name 一一对应,用于区分不同卡种(储值卡/活动抵用券/酒水卡/台费卡)。|外键|
+|card_type_name|VARCHAR(32)|memberCardTypeName|卡种名称(中文):• 储值卡:通用储值卡;• 活动抵用券:活动送券型卡;• 酒水卡:指定用于酒水类消费;• 台费卡:指定用于台费消费。|-|
+|member_name|VARCHAR(64)|memberName|会员姓名/称呼(如“曾丹烨”“葛先生”“胡先生”),主要用于运营、客服和人工识别。|-|
+|member_mobile|VARCHAR(20)|memberMobile|会员手机号(完整号码字符串),是会员识别、营销触达的重要字段。|-|
+|balance_before|DECIMAL(18,2)|before|本次变动前的卡内余额,单位:元。可为 0、数百、数千等。|-|
+|change_amount|DECIMAL(18,2)|account_data|本次余额变动金额,单位:元:• 正数:余额增加(充值、赠送、调整加款等);• 负数:余额减少(消费扣款、退款冲减、活动抵扣等)。所有记录严格满足:balance_after = balance_before + change_amount(浮点精度内)。|-|
+|balance_after|DECIMAL(18,2)|after|本次变动后的卡内余额,单位:元。由 before + account_data 计算而得,在源数据中已给出。|-|
+|from_type|INT|from_type|余额变动来源类型枚举(控制业务含义与方向):• 1:日常消费扣款 —— change_amount 为负数,payment_method=0,表示用卡支付消费被扣余额;• 3:充值增加 —— change_amount 为正数,payment_method=4,表示顾客通过外部支付为卡充值(扫码、银行卡等);• 4:调整/赠送增加 —— change_amount 为正数,payment_method=3,通常为后台赠送或手工加款;• 7:充值退款 —— change_amount 为负数,remark='充值退款',表示对历史充值做退款,以减少卡内余额方式体现;• 9:活动抵用券相关余额冲减 —— change_amount 为负数,卡种为“活动抵用券”,site_id=0,表示活动券额度被扣回或结算;• 2:其他增加 —— 当前仅 1 条正数样本(+1865.80),具体业务类型不明,但可确定为余额增加类。总体上:1/7/9 为减余额类,2/3/4 为加余额类。|-|
+|payment_method|INT|payment_method|支付/变动渠道枚举(与源系统支付方式枚举一致):• 0:内部结算/无外部支付 —— 日常消费扣款、内部扣减、退款冲减等场景,新资金流不在本记录中产生;• 3:赠送/后台调整渠道 —— 与 from_type=4 搭配出现,表示此余额增加不是顾客付钱,而是后台发放或内部调账;• 4:充值外部支付渠道 —— 与 from_type=3 搭配出现,代表顾客通过某外部渠道完成充值(具体是微信/支付宝/银行卡等需要结合支付枚举表进一步映射)。|-|
+|change_time|DATETIME|create_time|余额变动时间(记录创建时间),格式 YYYY-MM-DD HH:MM:SS。通常紧邻实际交易发生时间,用于按时间线分析资金变动。|-|
+|is_delete|TINYINT|is_delete|逻辑删除标记:• 0:正常记录(当前样本全部为 0);• 1:逻辑删除(标记为删除但数据库保留,用于追溯)。分析时通常需要过滤掉 is_delete=1 的记录。|-|
+|remark|VARCHAR(255)|remark|余额变动备注信息。当前样本中主要为:• 空字符串:无额外说明;• 充值退款:明确标记该条记录为“充值退款”业务,与 from_type=7 完全对应。后续可能出现其他业务备注。|-|
+
+
+
+**dwd_member_balance_change_Ex**
+|数据库字段名|字段类型|来源字段(member_balance_changes.json)|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|balance_change_id|BIGINT|id|余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。|主键|
+|pay_site_name|VARCHAR(64)|paySiteName|余额变动发生门店名称,对应 site_id 的中文名。示例:朗朗桌球;当 site_id = 0 时通常为空字符串。纯展示冗余。|-|
+|register_site_name|VARCHAR(64)|registerSiteName|办卡门店名称,对应 register_site_id 的中文名。当前样本全部为 朗朗桌球,属于冗余展示。|-|
+|refund_amount|DECIMAL(18,2)|refund_amount|退款金额字段。在当前样本数据中全部为 0.00,推测用于区分“退回卡内余额”和“原路退回”等更细的退款模式,但目前未启用。|-|
+|operator_id|BIGINT|operator_id|操作员 ID,执行本次余额变动操作的员工账号主键。可关联员工/账号维度。|外键|
+|operator_name|VARCHAR(64)|operator_name|操作员名称及职位说明,例如:收银员:郑丽珊、店长:谢晓洪 等,是对 operator_id 的可读冗余。|-|
+
+**dwd_member_balance_change 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|balance_change_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|发生变动的门店。|
+|register_site_id|外键|dim_site|site_id|办卡门店。|
+|tenant_member_id|外键|dim_member|member_id|租户内会员。|
+|system_member_id|外键|dim_system_member|system_member_id|全局会员。|
+|tenant_member_card_id|外键|dim_member_card_account|member_card_id|对应的会员卡账户。|
+|card_type_id|外键|dim_card_type|card_type_id|卡种。|
+|payment_method|外键|dim_payment_method|payment_method_id|支付/变动渠道。|
+|operator_id|外键|dim_staff|staff_id|操作员(Ex 表字段)。|
+
+------------------------------------------------------------
+
+### 团购券核销
+来自 group_buy_redemption_records.json 中各条记录。每行代表一次团购券使用/核销事件。
+
+**dwd_groupbuy_redemption**
+|数据库字段名|字段类型|来源字段(group_buy_redemption_records.json)|说明(含枚举与取值说明)|角色(主键/外键/-)|业务重要性|
+|---|---|---|---|---|---|
+|redemption_id|bigint|id|团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。|主键| |
+|tenant_id|bigint|tenant_id|租户/品牌 ID。与其他表统一的租户标识,用于品牌维度聚合。|外键|重要|
+|site_id|bigint|site_id|门店 ID。与门店维度及其他业务事实中的 site_id 一致。|外键|重要|
+|table_id|bigint|table_id|球台 ID。与台桌维度表中的 id 对应,用于确定具体哪一张球台。|外键|重要|
+|tenant_table_area_id|bigint|tenant_table_area_id|租户级台区组合 ID。与团购套餐定义中的 tenant_table_area_id_list 元素对应,表示该券实际使用时所在的台区组合。用于校验券的适用台区是否匹配实际台桌。|外键|重要|
+|table_charge_seconds|int|table_charge_seconds|本次结算中该球台总计计费的秒数(整台计费时间)。当台上除了券覆盖时长之外还有额外计费时间时,该值会大于券核销时长。|-|重要|
+|order_trade_no|bigint|order_trade_no|订单交易号。与台费流水、商品销售、助教服务、小票详情等表的 order_trade_no 一致,用于将同一笔结账中的所有明细串联起来。|外键|重要|
+|order_settle_id|bigint|order_settle_id|结算单 ID。与结账记录和小票详情中的结算主键对应,用于从团购券核销记录跳转到整单结算。|外键|重要|
+|order_coupon_id|bigint|order_coupon_id|订单中的“券使用记录 ID”。与平台或内部券核销表中的主键一致,用于在订单内部定位这条券使用记录。当前与 coupon_origin_id 数值相等。|外键|重要|
+|coupon_origin_id|bigint|coupon_origin_id|上游系统或第三方平台中该券记录的主键 ID。可在平台验券记录中查到券的来源平台、原订单等。当前与 order_coupon_id 数值一致,但语义是“券来源 ID”。|外键|重要|
+|promotion_activity_id|bigint|promotion_activity_id|促销活动 ID。每条记录对应一个活动主键,用于识别券所属的促销活动或团购活动。|外键|重要|
+|promotion_coupon_id|bigint|promotion_coupon_id|团购套餐定义 ID。与 group_buy_packages.json 中的 id 一一对应,表示当前使用的是哪一种团购套餐(例如某款“一小时套餐”“两小时套餐”)。|外键|重要|
+|order_coupon_channel|tinyint|order_coupon_channel|券渠道类型枚举。观测值:1(大量记录)、2(少量记录)。用于区分券的来源渠道,例如不同团购平台或内部券。具体数值与渠道名称的映射由业务配置决定。|外键|重要|
+|ledger_unit_price|decimal(18,2)|ledger_unit_price|本次券在台费侧对应的标准单价,单位元/小时。典型值如 29.9、39.9、59.9、69.9 等。与门店台费计费规则中的单价相对应,用于计算券对应的金额。|-|重要|
+|ledger_count|int|ledger_count|本次券实际核销的计费秒数。大部分记录等于 promotion_seconds,少数略小于标准时长,表示这张券只覆盖了本次台费的一部分时长。|-|重要|
+|ledger_amount|decimal(18,2)|ledger_amount|本次团购券实际冲抵台费的金额。大部分记录中该值与 coupon_money 相等,少数存在小数差异,来源于按单价与秒数换算的结果。|-|重要|
+|coupon_money|decimal(18,2)|coupon_money|本次核销时,团购券在门店侧对应的金额额度(可抵扣金额)。同一种 promotion_coupon_id 下,该值固定,例如某套餐固定为 48.00 元、某套餐固定为 96.00 元等。|-|重要|
+|promotion_seconds|int|promotion_seconds|团购套餐定义的标准时长权益,单位秒。观测枚举值为 3600、7200、14400,分别对应 1 小时、2 小时、4 小时。与团购套餐定义表中的 duration 字段一致。|-|重要|
+|coupon_code|varchar(64)|coupon_code|团购券券码字符串。每条记录一个唯一券码,例如“0107892475999”。用于与平台验券记录、券购买记录等做一一对应,追踪券的全生命周期。|外键|重要|
+|is_single_order|tinyint|is_single_order|是否作为单独订单行。观测值:1 为主,表示以独立条目方式结算;0 为个别记录,表示嵌入某种组合结算结构。具体业务含义依赖上层订单结构设计。|-|重要|
+|is_delete|tinyint|is_delete|逻辑删除标记。0 表示正常记录,1 表示逻辑删除但数据仍保留用于追溯。当前样本全部为 0,用于过滤有效记录。|-|重要|
+|ledger_name|varchar(128)|ledger_name|团购项目记账名称,如“全天A区中八一小时”“B区桌球一小时”“中八、斯诺克包厢两小时”等。通常与团购套餐名称相近,用于报表展示和套餐维度分析。|-|重要|
+|create_time|datetime|create_time|本条团购券核销流水的创建时间,通常即核销时间,格式为“YYYY-MM-DD HH:MM:SS”。用于时间维度分析和数据分区。|-|重要|
+
+
+
+**dwd_groupbuy_redemption_Ex**
+来自 group_buy_redemption_records.json 中各条记录。每行代表一次团购券使用/核销事件。
+
+|数据库字段名|字段类型|来源字段(group_buy_redemption_records.json)|说明(含枚举与取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|redemption_id|bigint|id|团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。|主键|
+|site_name|varchar(64)|siteName|门店名称。当前样本全部为同一门店,仅作冗余展示。|-|
+|table_name|varchar(64)|tableName|球台名称或台号。如 A7、A11、B1 等。用于业务报表展示与人工识别。|-|
+|table_area_name|varchar(64)|tableAreaName|台区名称。观测枚举值包括 A区、B区、斯诺克区、麻将房。实际取值随门店台区配置变化。|-|
+|order_pay_id|bigint|order_pay_id|支付流水 ID。部分记录为 0,表示未在当前导出范围内关联到具体支付记录。真实含义为“指向支付记录表中的支付流水”。|外键|
+|goods_option_price|decimal(18,2)|goodsOptionPrice|商品规格价格,用于商品类促销分摊时使用。当前在团购券核销场景中全部为 0,仅作为结构预留。|-|
+|goods_promotion_money|decimal(18,2)|goods_promotion_money|本次券使用中分摊到“商品”部分的促销金额。当前所有记录为 0,说明本门店的团购券未用于商品抵扣。|-|
+|table_service_promotion_money|decimal(18,2)|table_service_promotion_money|本次券使用中分摊到“台费服务费”部分的促销金额。当前样本全部为 0,结构上用于支持更细粒度的费用拆分。|-|
+|assistant_promotion_money|decimal(18,2)|assistant_promotion_money|本次券使用中分摊到“助教服务”的促销金额。当前全部为 0,说明团购券尚未用于助教服务的抵扣。|-|
+|assistant_service_promotion_money|decimal(18,2)|assistant_service_promotion_money|进一步细分助教服务对应的促销金额。当前为 0,仅预留结构以支持复杂场景。|-|
+|reward_promotion_money|decimal(18,2)|reward_promotion_money|本次促销中属于“奖励金、积分”等来源的促销金额分摊。当前为 0,预留用于积分或奖励金同时参与活动时的金额拆分。|-|
+|recharge_promotion_money|decimal(18,2)|recharge_promotion_money|来自“充值赠送”等储值优惠的促销金额分摊。当前为 0,预留用于将来区分“券优惠”和“充值赠送优惠”的场景。|-|
+|offer_type|tinyint|offer_type|优惠类型枚举。当前样本值全部为 1,表示本门店使用的团购券均为同一类型(例如“套餐券”)。其他取值可能对应满减、折扣、代金券等优惠类型,在本数据中未出现。|-|
+|ledger_status|tinyint|ledger_status|流水状态。观测值全部为 1。常规含义为:1 表示正常有效记录;其他值预留用于表示作废、撤销、未生效等状态。当前导出仅包含正常状态记录。|-|
+|operator_id|bigint|operator_id|执行本次券核销操作的操作员 ID。可与员工维度表对接,用于分析不同操作员的核销行为与绩效。|外键|
+|operator_name|varchar(64)|operator_name|操作员名称及角色说明,例如“收银员:郑丽珊”。与 operator_id 冗余,对报表展示友好,但不参与模型关联。|-|
+|salesman_user_id|bigint|salesman_user_id|营业员用户 ID。当前全部为 0,表示本门店在团购券场景未单独记录营业员信息。|外键|
+|salesman_name|varchar(64)|salesman_name|营业员姓名。当前为空字符串。结构上用于记录拉单或促销的业务员信息。|-|
+|salesman_role_id|bigint|salesman_role_id|营业员角色 ID。当前为 0,预留用于标识营业员在组织中的角色类型。|-|
+|salesman_org_id|bigint|sales_man_org_id|营业员所属组织 ID。来源字段为 sales_man_org_id,DWD 层统一命名为 salesman_org_id。当前为 0,用于将来对接组织架构维度。|-|
+|ledger_group_name|varchar(128)|ledger_group_name|团购项目的记账分组名称。当前全部为空,预留给将来按团购项目大类分组(例如“团购台费”“团购包厢”)使用。|-|
+
+**dwd_groupbuy_redemption 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|redemption_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|table_id|外键|dim_table|table_id|核销所在台桌。|
+|tenant_table_area_id|外键|dim_table_area_group|tenant_table_area_group_id|租户级台区分组。|
+|promotion_coupon_id|外键|dim_groupbuy_package|groupbuy_package_id|对应的团购套餐定义。|
+|promotion_activity_id|外键|dim_promotion_activity|promotion_activity_id|所属促销活动。|
+|order_coupon_channel|外键|dim_coupon_channel|coupon_channel_id|券来源渠道。|
+|order_settle_id|外键|dwd_settlement_head|order_settle_id|结账主单。|
+|order_trade_no|业务键|dwd_table_fee_log / dwd_payment|order_trade_no|订单级串联键。|
+|order_pay_id|外键|dwd_payment|payment_id|支付流水(Ex 表字段)。|
+|coupon_code|业务键|dwd_platform_coupon_redemption|coupon_code|与平台券核销记录按券码对齐。|
+|operator_id|外键|dim_staff|staff_id|核销操作员(Ex 表字段)。|
+|salesman_user_id|外键|dim_staff|staff_id|营业员(Ex 表字段)。|
+
+
+------------------------------------------------------------
+
+### 第三方平台券核销
+来自 platform_coupon_redemption_records.json。每条记录代表一次第三方团购券的核销,用于追踪渠道引流和兑换。
+
+**dwd_platform_coupon_redemption**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|platform_coupon_redemption_id|bigint|id|平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。|主键|
+|tenant_id|bigint|tenant_id|租户 ID,品牌级别标识。例如整套系统中的“朗朗桌球”品牌。与其他表的 tenant_id 一致,用于划分租户数据域。|外键|
+|site_id|bigint|site_id|门店 ID。与门店维度 dim_site.site_id 对应,用于区分不同门店。siteProfile.id 与此字段相同,本表不再冗余门店快照。|外键|
+|coupon_code|varchar(64)|coupon_code|第三方团购券券码,顾客出示的核销码。当前样本中全表唯一,可视为业务自然主键,用于验券、对账、查询。|-|
+|coupon_channel|tinyint|coupon_channel|券来源渠道枚举,表示第三方平台渠道编号。观测值:1,2。具体含义需结合系统配置,一般可理解为:1 表示平台渠道 1(主平台),2 表示平台渠道 2(其他入口或子平台)。|-|
+|coupon_name|varchar(200)|coupon_name|第三方团购券产品名称,例如“【全天可用】中八桌球一小时(A区)”“1小时中八台球【11月特惠】(A区)”等。用于报表展示和区分不同团购产品。| |
+|sale_price|decimal(10,2)|sale_price|顾客在第三方平台实际支付的团购售价,例如 11.11、29.90、39.90 等。始终小于 coupon_money,体现“折后价”。|-|
+|coupon_money|decimal(10,2)|coupon_money|券面值或套餐价值,即系统认为该券可抵扣的金额,例如 48.00、58.00、68.00、96.00、116.00、288.00。与 coupon_name 有固定对应关系。|-|
+|coupon_free_time|int|coupon_free_time|券附带的赠送时长,单位:秒。当前样本全部为 0,表示无独立赠送时长。若未来有赠送时间型券,则该字段存储赠送的秒数。|-|
+|channel_deal_id|bigint|channel_deal_id|渠道侧团购商品 ID(第三方平台 dealId)。值域有限(约 9 个值),与 coupon_name 一一对应。用于对接第三方接口和按平台商品维度统计。|- 或 外键(预留)|
+|deal_id|bigint|deal_id|平台/系统侧团购商品 ID。多数记录为非 0 整数,也有部分为 0。与 coupon_name 存在稳定对应关系,0 表示内部未配置或未同步。未来可作为内部团购商品维度外键。|外键(预留)|
+|group_package_id|bigint|group_package_id|内部“团购套餐”定义表主键 ID。当前样本中全部为 0,表示平台券尚未映射到自有团购套餐;从设计上是预留的外键字段。|外键|
+|site_order_id|bigint|site_order_id|门店内部订单 ID。本次平台券核销所挂靠的店内订单号。用于与结账记录、台费流水、商品销售等事实表通过订单维度关联。|外键|
+|table_id|bigint|table_id|使用团购券的球台 ID。与 dim_site_table.table_id 对应,用于统计每张球台的第三方平台引流情况。|外键|
+|certificate_id|varchar(64)|certificate_id|第三方平台侧券实例 ID(凭证 ID),通常为 16–19 位数字字符串。用于与外部平台对账与查询核销结果。存在重复值,不能单独作为唯一键。|-|
+|verify_id|varchar(64)|verify_id|第三方平台核销记录 ID。大部分记录为空,少量有值。存在时可用于精确反查平台侧核销记录。|-|
+|use_status|tinyint|use_status|券使用状态枚举。观测值:1、2。1 表示已使用/已核销(正常消耗);2 表示已退款/已撤销或使用后反冲的状态。是判断券生命周期状态的核心字段。|-|
+|is_delete|tinyint|is_delete|逻辑删除标志。0 表示未删除;1 表示已逻辑删除。与 use_status 独立:即便业务状态异常(如 use_status=2),也可能 is_delete 仍为 0 以保留记录。|-|
+|create_time|datetime|create_time|系统记录创建时间,即核销记录写入本系统的时间。格式为 YYYY-MM-DD HH:MM:SS。通常与 consume_time 相差约 1 秒。|-|
+|consume_time|datetime|consume_time|券被核销/使用的业务时间,代表实际团购券使用发生的时间点。后续按核销日期统计核销量时以该字段为准。|-|
+
+
+**dwd_platform_coupon_redemption_Ex**
+
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色|
+|---|---|---|---|---|
+|platform_coupon_redemption_id|bigint|id|平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。|主键|
+|coupon_cover|varchar(255)|coupon_cover|券封面图片地址 URL,用于前端展示团购券图片。对经营分析和结算逻辑无影响。|-|
+|coupon_remark|varchar(255)|coupon_remark|券描述或备注信息,用于展示券规则、说明文字。未参与计算和关联逻辑。|-|
+|groupon_type|tinyint|groupon_type|团购券类型枚举。当前样本全部为 1。推断含义:1 表示标准团购券,其他值预留为次卡、套餐券、权益券等类型。|-|
+|operator_id|bigint|operator_id|执行验券操作的员工/收银员账号 ID。当前样本中多数为同一值。可与员工/账号维度表关联。|外键|
+|operator_name|varchar(50)|operator_name|操作员姓名或显示名,例如“收银员:郑丽珊”。是 operator_id 的冗余展示字段,用于报表展示。|-|
+
+
+
+**dwd_platform_coupon_redemption 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|platform_coupon_redemption_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|table_id|外键|dim_table|table_id|核销所在台桌。|
+|coupon_channel|外键|dim_coupon_channel|coupon_channel_id|第三方渠道。|
+|deal_id|外键|dim_platform_deal|deal_id|平台商品/项目。|
+|group_package_id|外键|dim_groupbuy_package|groupbuy_package_id|内部映射的团购套餐。|
+|site_order_id|外键|dwd_settlement_head|order_settle_id|挂靠的店内订单。|
+|coupon_code|业务键|dwd_groupbuy_redemption|coupon_code|可与内部团购核销按券码对齐。|
+|operator_id|外键|dim_staff|staff_id|核销操作员(Ex 表字段)。|
+
+
+
+------------------------------------------------------------
+
+### 充值结算
+来自 recharge_settlements.json的settleList.settleList.。每行是一条充值订单,记录充值金额、赠送金额及是否首充。
+
+**dwd_recharge_order**
+|数据库字段名|字段类型|来源字段(JSON 路径)|说明(含枚举/取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|recharge_order_id|bigint|id|充值结算记录主键;唯一标识一条充值/撤销记录。|主键|
+|tenant_id|int|tenantId|租户/品牌 ID;与其他 JSON 中 tenantId 含义一致。|外键(dim_tenant)|
+|site_id|int|siteId|门店 ID;与 siteProfile.id 一致,用于关联门店维度。|外键(dim_site)|
+|member_id|bigint|memberId|会员 ID;对应会员档案中的 tenantMemberInfos.id。标识给哪个会员充值。|外键(dim_member)|
+|member_name_snapshot|varchar|memberName|会员姓名/昵称快照,可能是名称或手机号字符串。|-|
+|member_phone_snapshot|varchar|memberPhone|会员手机号快照。|-|
+|tenant_member_card_id|bigint|tenantMemberCardId|会员卡实例 ID(某张具体卡);可关联 dim_member_card_account。|外键(dim_member_card_account)|
+|member_card_type_name|varchar|memberCardTypeName|会员卡类型名称;当前样例主要有:“储值卡”、“月卡”。|-|
+|settle_relate_id|bigint|settleRelateId|结算关联 ID;用于与支付记录等跨表关联(类似业务单 ID)。|外键(与支付/结算域软关联)|
+|settle_type|tinyint|settleType|结算类型枚举:5=“充值订单”(正常充值);7=“充值撤销”(冲销记录)。|-|
+|settle_name|varchar|settleName|结算类型名称:"充值订单"、"充值撤销";前端展示用。|-|
+|is_first|tinyint|isFirst|是否首充标记。取值:1 或 2。理论含义类似“是否首充”,但 1/2 的精确定义需系统字典确认。|-|
+|pay_amount|decimal(18,2)|payAmount|本条记录的充值金额(可为正/负):正数=实际充值金额;负数=撤销流水金额(settleType=7)。|-|
+|refund_amount|decimal(18,2)|refundAmount|对该充值订单的退款金额(通常为正数);原始充值单上为已退款金额,对应会有一条负数的“充值撤销”记录。|-|
+|point_amount|decimal(18,2)|pointAmount|计入会员账户的储值/积分金额;多数情况下等于 pay_amount 的绝对值;撤销记录一般为 0。|-|
+|cash_amount|decimal(18,2)|cashAmount|现金收款金额;样本中少数为 3000/5000,其余为 0。|-|
+|payment_method|tinyint|paymentMethod|支付方式编码。样本取值:1、2、4;具体对应渠道(现金/微信/支付宝/银行卡等)需系统“支付方式字典”确认。|-|
+|create_time|datetime|createTime|充值记录创建时间(收银完成时间);用于时间分区、统计。|-|
+|pay_time|datetime|payTime|支付完成时间;通常与 create_time 接近或相同。|-|
+
+
+
+**dwd_recharge_order_Ex**
+|数据库字段名|字段类型|来源字段(JSON 路径)|说明(含枚举/取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|recharge_order_id|bigint|id|充值结算记录主键;唯一标识一条充值/撤销记录。|主键|
+|site_name_snapshot|varchar|siteName|门店名称快照,如“朗朗桌球”;仅用于展示,门店改名后本字段不变。|-|
+|settle_status|tinyint|settleStatus|结算状态;当前数据全部为 2,推测 2=已完成。其它状态未出现在样本中。|-|
+|is_bind_member|boolean|isBindMember|是否绑定为会员/其他绑定标记;当前所有记录为 False,而又都有 memberId,实际业务含义不清。|-|
+|is_activity|boolean|isActivity|是否关联营销活动;当前全部为 False,表示样本周期内充值未绑定活动。|-|
+|is_use_coupon|boolean|isUseCoupon|本次充值是否使用优惠券;当前样本全部为 False。结构上预留“充值用券”的能力。|-|
+|is_use_discount|boolean|isUseDiscount|是否使用折扣(如充值折扣);样本中全为 False。|-|
+|can_be_revoked|boolean|canBeRevoked|当前记录是否仍可撤销;样本中全为 False(导出时均不可撤销)。|-|
+|online_amount|decimal(18,2)|onlineAmount|线上支付金额(如微信、支付宝等);当前样本为 0,但字段为支付渠道拆分预留。|-|
+|balance_amount|decimal(18,2)|balanceAmount|从账户余额中支付的金额;充值场景通常为 0(用余额充值没有实际意义)。|-|
+|card_amount|decimal(18,2)|cardAmount|从其他储值卡或某种卡余额支付的金额;当前样本全为 0。|-|
+|coupon_amount|decimal(18,2)|couponAmount|使用券直接支付的金额(如储值券);当前样本为 0。|-|
+|recharge_card_amount|decimal(18,2)|rechargeCardAmount|充值到卡上的金额(与 point_amount 区分不同资金属性);样本为 0,结构预留。|-|
+|gift_card_amount|decimal(18,2)|giftCardAmount|赠送卡金额(如买 1000 送 100 的赠送部分);当前样本为 0。|-|
+|prepay_money|decimal(18,2)|prepayMoney|预付款金额(订金);当前样本为 0,充值未启用此场景。|-|
+|consume_money|decimal(18,2)|consumeMoney|消费总金额;在充值文件中全部为 0,实际用于消费场景(台费/商品)的结算模型复用字段。|-|
+|goods_money|decimal(18,2)|goodsMoney|商品消费金额(充值记录中为 0)。|-|
+|real_goods_money|decimal(18,2)|realGoodsMoney|实际应计商品金额(扣除折扣后);充值记录中为 0。|-|
+|table_charge_money|decimal(18,2)|tableChargeMoney|台费金额;充值记录中为 0,来自通用结算模型。|-|
+|service_money|decimal(18,2)|serviceMoney|服务项目金额(如助教、其他服务);充值中为 0。|-|
+|activity_discount|decimal(18,2)|activityDiscount|营销活动折扣金额;当前样本为 0。|-|
+|all_coupon_discount|decimal(18,2)|allCouponDiscount|各类优惠券、团购券综合折扣金额;样本为 0。|-|
+|goods_promotion_money|decimal(18,2)|goodsPromotionMoney|商品促销优惠金额;样本为 0。|-|
+|assistant_promotion_money|decimal(18,2)|assistantPromotionMoney|助教相关促销优惠金额;样本为 0。|-|
+|assistant_pd_money|decimal(18,2)|assistantPdMoney|助教配单金额/相关费用;样本为 0。|-|
+|assistant_cx_money|decimal(18,2)|assistantCxMoney|助教冲销/促销相关金额;样本为 0。|-|
+|assistant_manual_discount|decimal(18,2)|assistantManualDiscount|助教手工减免金额;样本为 0。|-|
+|coupon_sale_amount|decimal(18,2)|couponSaleAmount|券/套餐销售金额(售卖券时使用);充值场景中为 0。|-|
+|member_discount_amount|decimal(18,2)|memberDiscountAmount|因会员折扣产生的优惠金额;在充值样本中为 0。|-|
+|point_discount_price|decimal(18,2)|pointDiscountPrice|积分抵扣产生的价差(价格部分);样本为 0。|-|
+|point_discount_cost|decimal(18,2)|pointDiscountCost|积分抵扣对应的成本金额;样本为 0。|-|
+|adjust_amount|decimal(18,2)|adjustAmount|手工调整金额(非抹零);样本为 0。|-|
+|rounding_amount|decimal(18,2)|roundingAmount|抹零金额(四舍五入产生的差额);样本为 0。|-|
+|operator_id|bigint|operatorId|操作该笔充值的收银员/员工 ID。|外键(将来可关联 dim_staff)|
+|operator_name_snapshot|varchar|operatorName|操作员姓名快照,便于直接阅读;与 operator_id 对应。|-|
+|salesman_user_id|bigint|salesManUserId|营业员用户 ID;当前样本全部为 0。|外键(潜在 dim_staff)|
+|salesman_name|varchar|salesManName|营业员/销售员姓名;样本为空字符串。|-|
+|order_remark|varchar|orderRemark|充值订单备注,如手工说明;当前样本为空。|-|
+|table_id|int|tableId|台桌 ID;充值场景下全部是 0,表示该订单不挂具体球台。|-|
+|serial_number|int|serialNumber|流水/小票序号;当前样本全部为 0,本门店未启用。|-|
+|revoke_order_id|bigint|revokeOrderId|撤销相关订单 ID(被撤销原单或撤销单指针);样本中存在值但逻辑未完全启用。|-|
+|revoke_order_name|varchar|revokeOrderName|撤销单名称/说明;样本全为空。|-|
+|revoke_time|datetime|revokeTime|撤销时间;当前样本为空,撤销信息主要通过负数流水与 refund_amount 表达。|-|
+
+
+
+
+**dwd_recharge_order 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|recharge_order_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|member_id|外键|dim_member|member_id|会员。|
+|tenant_member_card_id|外键|dim_member_card_account|member_card_id|会员卡账户。|
+|payment_method|外键|dim_payment_method|payment_method_id|支付方式。|
+|settle_relate_id|外键|dwd_payment|relate_id|对应支付/业务单关联键。|
+|operator_id|外键|dim_staff|staff_id|收银员/操作员(Ex 表)。|
+|salesman_user_id|外键|dim_staff|staff_id|营业员(Ex 表)。|
+
+
+
+------------------------------------------------------------
+
+### 支付流水
+来自 payment_transactions.json。每行代表一笔支付或收款流水,与结算单、充值单等关联。只有 pay_status=2 的支付成功记录被导出。
+
+**dwd_payment**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|payment_id|bigint|payment_transactions.id|支付流水主键ID。与源系统 id 一致。每条支付流水唯一标识一条支付行为(包括金额为 0 的记录)。|主键|
+|site_id|bigint|payment_transactions.site_id|门店ID。当前样本中全部为同一门店 2790685415443269。在数仓中外键关联 dim_site.site_id。|外键|
+|relate_type|int|payment_transactions.relate_type|业务关联类型枚举,用来区分这条支付流水对应哪一类业务单据:• 2:结账单支付,对应结账记录 settlement_records 中的结账单;• 5:会员卡充值/账户变动类支付,对应会员余额/充值业务单号,在会员余额变更或充值结算中复用;• 1:其他业务类型,目前样本中仅有 1 条记录,具体业务含义待业务侧补充。|-|
+|relate_id|bigint|payment_transactions.relate_id|关联业务记录ID,配合 relate_type 使用,是一个“多态外键”:• 当 relate_type = 2 时:relate_id = settlement_records.settleList.id(结账记录主键,对应 dwd_settlement_head_di.order_settle_id);• 当 relate_type = 5 时:relate_id = 会员卡余额变动/充值业务单号,在会员余额变更流水中同名字段使用;• 当 relate_type = 1 时:关联具体业务尚未确认,仅可视为预留类型。|外键(多业务类型)|
+|pay_amount|decimal(18,2)|payment_transactions.pay_amount|本次支付金额,单位元。为收入类字段,当前样本全部为非负数:• 正数:实际通过该支付方式收取的金额;• 0:仍生成支付流水,但实收金额为 0(例如整单由会员优惠、团购券、余额等抵扣),当前样本中有 140 条记录金额为 0。|-|
+|pay_status|int|payment_transactions.pay_status|支付状态枚举。当前样本中仅出现:• 2:支付成功。其它可能的状态(未支付、支付中、失败、已退款等)在本次导出中未出现,需以后按系统支付状态配置补充。由于本 JSON 仅导出成功记录,可以视作“成功支付流水视图”。|-|
+|payment_method|int|payment_transactions.payment_method|支付方式枚举。当前样本中出现的取值:• 2:共 140 条记录;• 4:共 60 条记录。具体取值与“支付方式配置表”对应,例如可能代表现金、扫码支付、银行卡等。由于配置表未导出,在数仓中应作为枚举码字段,通过后续 dim_payment_method 进行解码。不要在数仓层擅自写死“2=微信、4=支付宝”等含义。|外键(预期关联支付方式维度)|
+|online_pay_channel|int|payment_transactions.online_pay_channel|线上支付通道枚举。用于进一步细分线上渠道,例如:• 0:无线上通道/线下,或未区分具体线上通道(当前样本全部为 0);• 1:微信(推测,未在样本中出现);• 2:支付宝(推测,未在样本中出现)。目前门店在当前时间段内尚未使用该字段进行实际区分,业务含义需结合正式配置确认。|-|
+|create_time|datetime|payment_transactions.create_time|支付流水创建时间,格式 YYYY-MM-DD HH:MM:SS。通常是发起支付请求的时间。当前样本中 create_time 与 pay_time 多数相同,但模型上允许两者不同(例如异步支付)。|-|
+|pay_time|datetime|payment_transactions.pay_time|支付完成时间(支付成功时间戳),格式 YYYY-MM-DD HH:MM:SS。用于统计资金实际入账时间,以及与结账时间进行对齐分析。|-|
+|pay_date|date|由 payment_transactions.pay_time 派生|支付日期分区字段,从 pay_time 截取 YYYY-MM-DD 得到。例如 pay_time = '2025-11-09 23:35:57' 时,pay_date = '2025-11-09'。用于 DWD 表按天分区和日粒度汇总。|-|
+
+**dwd_payment 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|payment_id|主键|-|-|主键字段;支付流水唯一键,Ex 表复用。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|payment_method|外键|dim_payment_method|payment_method_id|支付方式枚举。|
+|online_pay_channel|外键|dim_online_pay_channel|online_pay_channel_id|线上子渠道(预留维度)。|
+|relate_type|-|业务字典|-|区分业务主单类型。|
+|relate_id|外键(多态)|dwd_settlement_head / dwd_recharge_order / dwd_member_balance_change|order_settle_id / recharge_order_id / balance_change_id|随 relate_type 变化的业务主单 ID。|
+|pay_date|分区键|-|-|日分区字段。|
+
+------------------------------------------------------------
+
+### 退款流水
+来自 refund_transactions.json。每行代表一笔退款,对应原支付流水。退款金额以负数存储在 pay_amount 字段;字段 refund_amount 全部为 0,实际退款金额需取 pay_amount 的绝对值。
+
+**dwd_refund**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|refund_id|bigint|id|退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。|主键|
+|tenant_id|bigint|tenant_id|租户/品牌 ID,标识所属商户。与其他表中的 tenant_id 一致。|外键|
+|site_id|bigint|site_id|门店 ID。与门店维度 dim_site.site_id 对应,用于分门店分析。|外键|
+|relate_type|int|relate_type|业务类型枚举,指示本退款对应哪类业务主单:当前样本值 {2, 5}:2=消费/结账类业务;5=充值/储值类业务(根据分析文档推断,具体定义需以业务字典为准)。与 relate_id 组合使用。|-|
+|relate_id|bigint|relate_id|关联的业务主键 ID。含义依赖 relate_type:relate_type=2 时通常指结账主单 ID;relate_type=5 时通常指充值/储值业务单 ID。同一个 relate_id 可能有多笔退款(分批退款)。|外键|
+|pay_amount|decimal(18,2)|pay_amount|本次退款的资金金额,统一为负数。绝对值即退款金额。例如 -5000.00 表示退款 5000 元。是后续退款金额统计的主字段。|-|
+|channel_fee|decimal(18,2)|channel_fee|第三方支付渠道对本次退款收取的手续费。当前样本全部为 0.00,但从设计看用于“通道成本核算”。|-|
+|pay_time|datetime|pay_time|退款在支付渠道/系统中发生的时间(退款完成时间)。用于对账及按时间统计退款。当前样本中等于 create_time。|-|
+|create_time|datetime|create_time|本条退款流水在系统内创建时间。与 pay_time 区分“记录生成时间 vs. 渠道时间”,当前样本中两者相同。|-|
+|payment_method|int|payment_method|支付方式枚举,指本次退款对应的原支付方式(如哪种通道)。样本中仅出现值 4;在支付记录中曾出现 {2,4} 两种值。含义:区分不同支付方式(如微信、支付宝、银行卡、现金、储值卡等),具体值与含义需参照支付方式配置表。|-|
+|member_id|bigint|member_id|关联的会员 ID,对应会员档案表主键。当前样本全部为 0,表示这些退款未绑定到具体会员。|外键|
+|member_card_id|bigint|member_card_id|关联的会员卡账户 ID,对应会员卡账户/储值卡维度主键。样本全部为 0,当前没有“退到会员卡”的记录。|外键|
+
+
+**dwd_refund_Ex**
+|数据库字段名|字段类型|来源字段|说明(含枚举值和取值说明)|角色(主键/外键/-)|
+|---|---|---|---|---|
+|refund_id|bigint|id|退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。|主键|
+|tenant_name|varchar(64)|tenantName|租户名称,例如“朗朗桌球”。与租户维度中的名称冗余。|-|
+|pay_sn|bigint|pay_sn|支付流水内部序号。退款记录中样本全部为 0,未看到实际使用场景,含义未从文档中说明。|-|
+|refund_amount|decimal(18,2)|refund_amount|设计上应为“本次退款金额(正数)”。当前样本全部为 0.00,系统实际使用的是 pay_amount 记录金额,此字段暂未启用。|-|
+|round_amount|decimal(18,2)|round_amount|退款过程中的舍入/抹零金额(例如因四舍五入产生的差额)。当前样本全部为 0.00。|-|
+|balance_frozen_amount|decimal(18,2)|balance_frozen_amount|与会员余额相关的“冻结金额”,如先冻结再退款的流程。当前样本全部为 0.00,且 member_id/member_card_id 为 0,说明本批退款没有涉及会员余额冻结。|-|
+|card_frozen_amount|decimal(18,2)|card_frozen_amount|与某张会员卡余额相关的冻结金额。样本全部为 0.00,未实际使用。|-|
+|pay_status|int|pay_status|退款状态枚举。样本中全部为 2。结合支付记录:2 表示“成功/已完成”。其他可能值(0=未处理,1=处理中等)未在样本中出现,具体以系统枚举为准。|-|
+|action_type|int|action_type|资金动作类型枚举。样本全部为 2。根据分析:1=支付,2=退款。退款流水恒为 2,用于与支付流水区分。|-|
+|is_revoke|int|is_revoke|是否为“撤销型”退款。枚举:0=正常退款;1=撤销原支付(撤销而非普通退货)。当前样本全部为 0。|-|
+|is_delete|int|is_delete|逻辑删除标志。枚举:0=未删除;1=已逻辑删除(保留记录,仅标记)。当前样本全部为 0。|-|
+|check_status|int|check_status|审核状态。样本全部为 1。推断:1=已审核/通过;其他值可能表示“待审核”“审核拒绝”等,具体需以系统字典为准。|-|
+|online_pay_channel|int|online_pay_channel|线上支付渠道枚举。样本中全部为 0。推断:0=线下或默认渠道;其他值(若有)可能代表微信、支付宝等子渠道。目前门店未实际使用该拆分。|-|
+|online_pay_type|int|online_pay_type|在线退款类型。样本全部为 0。推断:0=原路退回;其他值(若有)可能表示“退到余额”“退到其他银行卡”等。当前数据仅有默认策略。|-|
+|pay_terminal|int|pay_terminal|退款终端类型枚举。样本全部为 1。推断:1=前台收银端;其他值可能为小程序、自助机、后台等。用于区分退款来源终端。|-|
+|pay_config_id|int|pay_config_id|支付配置 ID,例如某个具体支付通道(微信商户号、银联通道等)的配置主键。样本全部为 0,说明当前未按此粒度区分或未导出。|外键|
+|cashier_point_id|int|cashier_point_id|收银点编号,例如前台1、前台2、自助机等。样本全部为 0,未实际区分收银点。|-|
+|operator_id|bigint|operator_id|执行退款操作的操作员 ID。样本全部为 0,说明导出中未包含操作员信息。若填充,对内部风控与员工考核很重要。|外键|
+|channel_payer_id|varchar(128)|channel_payer_id|支付渠道侧的付款人标识,如微信 openid、银行卡号掩码等。样本全部为空字符串,未使用。|-|
+|channel_pay_no|varchar(128)|channel_pay_no|第三方支付平台交易号(如微信支付单号、支付宝交易号等)。当前样本全部为空。若将来填充,对资金对账非常关键。|-|
+
+**dwd_refund 主外键关系**
+|键|属性|关联|被关联|说明|
+|---|---|---|---|---|
+|refund_id|主键|-|-|主键字段;Ex 表复用此键。|
+|tenant_id|外键|dim_tenant|tenant_id|租户/品牌 ID。|
+|site_id|外键|dim_site|site_id|门店 ID。|
+|payment_method|外键|dim_payment_method|payment_method_id|原支付方式。|
+|relate_type|-|业务字典|-|区分消费/充值等业务类型。|
+|relate_id|外键(多态)|dwd_settlement_head / dwd_recharge_order|order_settle_id / recharge_order_id|随 relate_type 变化的业务主单 ID。|
+|member_id|外键|dim_member|member_id|关联会员。|
+|member_card_id|外键|dim_member_card_account|member_card_id|关联会员卡账户。|
+|pay_config_id|外键|dim_pay_config|pay_config_id|支付配置(Ex 表)。|
+|cashier_point_id|外键|dim_cashier_point|cashier_point_id|收银点(Ex 表)。|
+|operator_id|外键|dim_staff|staff_id|退款操作员(Ex 表)。|
diff --git a/etl_billiards/tmp/dwd_schema_columns.txt b/tmp/etl_billiards_misc/tmp & Delete/dwd_schema_columns.txt
similarity index 100%
rename from etl_billiards/tmp/dwd_schema_columns.txt
rename to tmp/etl_billiards_misc/tmp & Delete/dwd_schema_columns.txt
diff --git a/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.bak b/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.bak
new file mode 100644
index 0000000..20a45b2
--- /dev/null
+++ b/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.bak
@@ -0,0 +1,1927 @@
+-- 文件:schema_ODS_doc.sql
+-- 说明:ODS 层 DDL,表名与示例 JSON 前缀对应,用于本地回放/调试。
+-- 编码:UTF-8
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS '表用途:ODS 原始明细,对应 JSON 文件 member_profiles.json,详见 member_profiles-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2790685415443269(样例对照);JSON字段:register_site_id';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:site_name';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2955204541320325(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2955204540009605(样例对照);JSON字段:system_member_id';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2790683528022853(样例对照);JSON字段:member_card_grade_code';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:储值卡(样例对照);JSON字段:member_card_grade_name';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:18620043391(样例对照);JSON字段:mobile';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:胡先生(样例对照);JSON字段:nickname';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:0.0(样例对照);JSON字段:point';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:0.0(样例对照);JSON字段:growth_value';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:0(样例对照);JSON字段:referrer_member_id';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:1(样例对照);JSON字段:status';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:1(样例对照);JSON字段:user_status';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '说明:同名 JSON 字段,业务含义详见 member_profiles-Analysis.md;示例:2025-11-08 01:29:33(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:member_profiles.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '表用途:ODS 原始明细,对应 JSON 文件 member_balance_changes.json,详见 member_balance_changes-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2790685415443269(样例对照);JSON字段:register_site_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:registerSiteName';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:paySiteName';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2957881605869253(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2799212845565701(样例对照);JSON字段:tenant_member_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2799219999295237(样例对照);JSON字段:tenant_member_card_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2799212844549893(样例对照);JSON字段:system_member_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:曾丹烨(样例对照);JSON字段:memberName';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:13922213242(样例对照);JSON字段:memberMobile';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2793249295533893(样例对照);JSON字段:card_type_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:储值卡(样例对照);JSON字段:memberCardTypeName';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:-120.0(样例对照);JSON字段:account_data';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:816.3(样例对照);JSON字段:before';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:696.3(样例对照);JSON字段:after';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:0.0(样例对照);JSON字段:refund_amount';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:1(样例对照);JSON字段:from_type';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:0(样例对照);JSON字段:payment_method';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2957881518788421(样例对照);JSON字段:relate_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:(样例对照);JSON字段:remark';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '说明:同名 JSON 字段,业务含义详见 member_balance_changes-Analysis.md;示例:2025-11-09 22:52:48(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:member_balance_changes.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '表用途:ODS 原始明细,对应 JSON 文件 member_stored_value_cards.json,详见 member_stored_value_cards-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2955204541320325(样例对照);JSON字段:tenant_member_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2955204540009605(样例对照);JSON字段:system_member_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2790685415443269(样例对照);JSON字段:register_site_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:site_name';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2955206162843781(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2790683528022856(样例对照);JSON字段:member_card_grade_code';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:活动抵用券(样例对照);JSON字段:member_card_grade_code_name';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:活动抵用券(样例对照);JSON字段:member_card_type_name';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:胡先生(样例对照);JSON字段:member_name';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:18620043391(样例对照);JSON字段:member_mobile';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2793266846533445(样例对照);JSON字段:card_type_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:(样例对照);JSON字段:card_no';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:1(样例对照);JSON字段:card_physics_type';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:balance';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:denomination';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:table_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:goods_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:assistant_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:assistant_reward_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:table_service_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:assistant_service_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:coupon_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:10.0(样例对照);JSON字段:goods_service_discount';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2(样例对照);JSON字段:assistant_discount_sub_switch';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2(样例对照);JSON字段:table_discount_sub_switch';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2(样例对照);JSON字段:goods_discount_sub_switch';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2(样例对照);JSON字段:assistant_reward_discount_sub_switch';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:table_service_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:assistant_service_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:goods_service_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:assistant_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:table_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:goods_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:coupon_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:100.0(样例对照);JSON字段:assistant_reward_deduct_radio';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:tableCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:tableServiceCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:goodsCarDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:goodsServiceCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:assistantCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:assistantServiceCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:assistantRewardCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:cardSettleDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:couponCardDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0.0(样例对照);JSON字段:deliveryFeeDeduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:(样例对照);JSON字段:use_scene';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:1(样例对照);JSON字段:able_cross_site';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:无样例(样例对照);JSON字段:able_site_transfer';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0(样例对照);JSON字段:is_allow_give';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0(样例对照);JSON字段:is_allow_order_deduct';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:(样例对照);JSON字段:bind_password';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:1(样例对照);JSON字段:goods_discount_range_type';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:[](样例对照);JSON字段:goodsCategoryId';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:[](样例对照);JSON字段:tableAreaId';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0(样例对照);JSON字段:effect_site_id';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2025-11-08 01:31:12(样例对照);JSON字段:start_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2225-01-01 00:00:00(样例对照);JSON字段:end_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0001-01-01 00:00:00(样例对照);JSON字段:disable_start_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:0001-01-01 00:00:00(样例对照);JSON字段:disable_end_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2025-11-09 07:48:23(样例对照);JSON字段:last_consume_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:2025-11-08 01:31:12(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:1(样例对照);JSON字段:status';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:1(样例对照);JSON字段:sort';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:(样例对照);JSON字段:tenantAvatar';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:(样例对照);JSON字段:tenantName';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:[](样例对照);JSON字段:pdAssisnatLevel';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '说明:同名 JSON 字段,业务含义详见 member_stored_value_cards-Analysis.md;示例:[](样例对照);JSON字段:cxAssisnatLevel';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:member_stored_value_cards.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS '表用途:ODS 原始明细,对应 JSON 文件 recharge_settlements.json,详见 recharge_settlements-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:tenantid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:siteid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:sitename';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:balanceamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:cardamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:cashamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:couponamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:createtime';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:memberid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:membername';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:tenantmembercardid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:membercardtypename';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:memberphone';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:tableid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:consumemoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:onlineamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:operatorid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:operatorname';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:revokeorderid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:revokeordername';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:revoketime';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:payamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:pointamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:refundamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:settlename';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:settlerelateid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:settlestatus';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:settletype';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:paytime';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:roundingamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:paymentmethod';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:adjustamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:assistantcxmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:assistantpdmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:couponsaleamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:memberdiscountamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:tablechargemoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:goodsmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:realgoodsmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:servicemoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:prepaymoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:salesmanname';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:orderremark';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:salesmanuserid';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:canberevoked';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:pointdiscountprice';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:pointdiscountcost';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:activitydiscount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:serialnumber';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:assistantmanualdiscount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:allcoupondiscount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:goodspromotionmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:assistantpromotionmoney';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:isusecoupon';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:isusediscount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:isactivity';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:isbindmember';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:isfirst';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:rechargecardamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '说明:同名 JSON 字段,业务含义详见 recharge_settlements-Analysis.md;示例:无样例(样例对照);JSON字段:giftcardamount';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:recharge_settlements.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS '表用途:ODS 原始明细,对应 JSON 文件 settlement_records.json,详见 settlement_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:tenantid';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:siteid';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:sitename';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:balanceamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:cardamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:cashamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:couponamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:createtime';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:memberid';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:membername';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:tenantmembercardid';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:membercardtypename';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:memberphone';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:tableid';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:consumemoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:onlineamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:operatorid';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:operatorname';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:revokeorderid';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:revokeordername';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:revoketime';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:payamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:pointamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:refundamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:settlename';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:settlerelateid';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:settlestatus';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:settletype';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:paytime';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:roundingamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:paymentmethod';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:adjustamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:assistantcxmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:assistantpdmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:couponsaleamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:memberdiscountamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:tablechargemoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:goodsmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:realgoodsmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:servicemoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:prepaymoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:salesmanname';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:orderremark';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:salesmanuserid';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:canberevoked';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:pointdiscountprice';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:pointdiscountcost';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:activitydiscount';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:serialnumber';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:assistantmanualdiscount';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:allcoupondiscount';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:goodspromotionmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:assistantpromotionmoney';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:isusecoupon';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:isusediscount';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:isactivity';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:isbindmember';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:isfirst';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:rechargecardamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '说明:同名 JSON 字段,业务含义详见 settlement_records-Analysis.md;示例:无样例(样例对照);JSON字段:giftcardamount';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:settlement_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS '表用途:ODS 原始明细,对应 JSON 文件 assistant_cancellation_records.json,详见 assistant_cancellation_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:2957675849518789(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:2790685415443269(样例对照);JSON字段:siteId';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "av…(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:泡芙(样例对照);JSON字段:assistantName';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:5.83(样例对照);JSON字段:assistantAbolishAmount';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:27(样例对照);JSON字段:assistantOn';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:214(样例对照);JSON字段:pdChargeMinutes';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:2791963816579205(样例对照);JSON字段:tableAreaId';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:C区(样例对照);JSON字段:tableArea';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:2793016660660357(样例对照);JSON字段:tableId';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:C1(样例对照);JSON字段:tableName';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:(样例对照);JSON字段:trashReason';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '说明:同名 JSON 字段,业务含义详见 assistant_cancellation_records-Analysis.md;示例:2025-11-09 19:23:29(样例对照);JSON字段:createTime';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:assistant_cancellation_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ birth_date TIMESTAMP,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ last_update_name TEXT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS '表用途:ODS 原始明细,对应 JSON 文件 assistant_accounts_master.json,详见 assistant_accounts_master-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2947562271297029(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:31(样例对照);JSON字段:assistant_no';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:小然(样例对照);JSON字段:nickname';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:张静然(样例对照);JSON字段:real_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:15119679931(样例对照);JSON字段:mobile';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2792011585884037(样例对照);JSON字段:team_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1组(样例对照);JSON字段:team_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2947562270838277(样例对照);JSON字段:user_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:20(样例对照);JSON字段:level';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:assistant_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2(样例对照);JSON字段:work_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:leave_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-11-02 08:00:00(样例对照);JSON字段:entry_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-11-03 08:00:00(样例对照);JSON字段:resign_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-11-01 08:00:00(样例对照);JSON字段:start_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-12-01 08:00:00(样例对照);JSON字段:end_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-11-02 15:55:26(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2025-11-03 18:32:07(样例对照);JSON字段:update_time';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:staff_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:staff_profile_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:10(样例对照);JSON字段:system_role_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(样例对照);JSON字段:avatar';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.birth_date IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0001-01-01 00:00:00(样例对照);JSON字段:birth_date';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:gender';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:height';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:weight';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:job_num';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:show_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:31(样例对照);JSON字段:show_sort';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:sum_grade';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:assistant_grade';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:get_grade_times';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:introduce';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:video_introduction_url';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:group_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:group_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:shop_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2(样例对照);JSON字段:charge_way';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:entry_type';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:allow_cx';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:is_guaranteed';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2(样例对照);JSON字段:salary_grant_enabled';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2(样例对照);JSON字段:light_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:online_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:cx_unit_price';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0.0(样例对照);JSON字段:pd_unit_price';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:last_table_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:last_table_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:2947562271215109(样例对照);JSON字段:person_org_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:serial_number';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:is_team_leader';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:criticism_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_update_name IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:无样例(样例对照);JSON字段:last_update_name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:1(样例对照);JSON字段:ding_talk_synced';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:site_light_cfg_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:(样例对照);JSON字段:light_equipment_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:entry_sign_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '说明:同名 JSON 字段,业务含义详见 assistant_accounts_master-Analysis.md;示例:0(样例对照);JSON字段:resign_sign_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:assistant_accounts_master.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ levelname TEXT,
+ site_assistant_id BIGINT,
+ skill_id BIGINT,
+ skillname TEXT,
+ system_member_id BIGINT,
+ tablename TEXT,
+ tenant_member_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS '表用途:ODS 原始明细,对应 JSON 文件 assistant_service_records.json,详见 assistant_service_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2957913441292165(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "av…(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2793020259897413(样例对照);JSON字段:site_table_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2957913171693253(样例对照);JSON字段:order_settle_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2957784612605829(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:order_pay_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2957788717240005(样例对照);JSON字段:order_assistant_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:1(样例对照);JSON字段:order_assistant_type';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:何海婷(样例对照);JSON字段:assistantName';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:27(样例对照);JSON字段:assistantNo';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:10(样例对照);JSON字段:assistant_level';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.levelname IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:初级(样例对照);JSON字段:levelname';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_assistant_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2946266869435205(样例对照);JSON字段:site_assistant_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2790683529513797(样例对照);JSON字段:skill_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skillname IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:基础课(样例对照);JSON字段:skillname';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.system_member_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:system_member_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tablename IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:S1(样例对照);JSON字段:tablename';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_member_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:tenant_member_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.user_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2946266868976453(样例对照);JSON字段:user_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2792011585884037(样例对照);JSON字段:assistant_team_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:泡芙(样例对照);JSON字段:nickname';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:27-泡芙(样例对照);JSON字段:ledger_name';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:(样例对照);JSON字段:ledger_group_name';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:206.67(样例对照);JSON字段:ledger_amount';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:7592(样例对照);JSON字段:ledger_count';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:98.0(样例对照);JSON字段:ledger_unit_price';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_status';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2025-11-09 21:18:18(样例对照);JSON字段:ledger_start_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2025-11-09 23:24:50(样例对照);JSON字段:ledger_end_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:manual_discount_amount';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:member_discount_amount';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:coupon_deduct_money';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:service_money';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:168.0(样例对照);JSON字段:projected_income';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:7592(样例对照);JSON字段:real_use_seconds';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:7560(样例对照);JSON字段:income_seconds';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2025-11-09 21:18:18(样例对照);JSON字段:start_use_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2025-11-09 23:24:50(样例对照);JSON字段:last_use_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2025-11-09 23:25:11(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:1(样例对照);JSON字段:is_single_order';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:is_trash';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:(样例对照);JSON字段:trash_reason';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:trash_applicant_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:(样例对照);JSON字段:trash_applicant_name';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:(样例对照);JSON字段:salesman_name';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_org_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_user_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2946266869336901(样例对照);JSON字段:person_org_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:add_clock';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:returns_clock';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:composite_grade';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0001-01-01 00:00:00(样例对照);JSON字段:composite_grade_time';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:skill_grade';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:service_grade';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0.0(样例对照);JSON字段:sum_grade';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:1(样例对照);JSON字段:grade_status';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:get_grade_times';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:0(样例对照);JSON字段:is_not_responding';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '说明:同名 JSON 字段,业务含义详见 assistant_service_records-Analysis.md;示例:2(样例对照);JSON字段:is_confirm';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:assistant_service_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS '表用途:ODS 原始明细,对应 JSON 文件 site_tables_master.json,详见 site_tables_master-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2791964216463493(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:siteName';
+COMMENT ON COLUMN billiards_ods.site_tables_master."appletQrCodeUrl" IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:https://pc-we.ficoo.vip/rootwww/prodwx38a48dd2bc3c1642?env=prod&type=1&id=279…(样例对照);JSON字段:appletQrCodeUrl';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:A区(样例对照);JSON字段:areaName';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2(样例对照);JSON字段:audit_status';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:charge_free';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2025-07-15 17:52:54(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:delay_lights_time';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2(样例对照);JSON字段:is_online_reservation';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:is_rest_area';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2(样例对照);JSON字段:light_status';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2(样例对照);JSON字段:only_allow_groupon';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:order_delay_time';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:1(样例对照);JSON字段:self_table';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:1(样例对照);JSON字段:show_status';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:2791963794329671(样例对照);JSON字段:site_table_area_id';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:空闲中(样例对照);JSON字段:tableStatusName';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:table_cloth_use_Cycle';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:1863727(样例对照);JSON字段:table_cloth_use_time';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:A1(样例对照);JSON字段:table_name';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0.0(样例对照);JSON字段:table_price';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:1(样例对照);JSON字段:table_status';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:temporary_light_second';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '说明:同名 JSON 字段,业务含义详见 site_tables_master-Analysis.md;示例:0(样例对照);JSON字段:virtual_table';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:site_tables_master.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS '表用途:ODS 原始明细,对应 JSON 文件 table_fee_discount_records.json,详见 table_fee_discount_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2957913441881989(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "av…(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2793020259897413(样例对照);JSON字段:site_table_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:{"id": 2793020259897413, "tenant_id": 2790683160709957, "tenant_name": "", "s…(样例对照);JSON字段:tableProfile';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2791961347968901(样例对照);JSON字段:tenant_table_area_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:1(样例对照);JSON字段:adjust_type';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:148.15(样例对照);JSON字段:ledger_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_count';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:(样例对照);JSON字段:ledger_name';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_status';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2790687322443013(样例对照);JSON字段:applicant_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:applicant_name';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2957913171693253(样例对照);JSON字段:order_settle_id';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2957784612605829(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_discount_records-Analysis.md;示例:2025-11-09 23:25:11(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:table_fee_discount_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS '表用途:ODS 原始明细,对应 JSON 文件 table_fee_transactions.json,详见 table_fee_transactions-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2957924029058885(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "av…(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2793003705192517(样例对照);JSON字段:site_table_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2791963794329671(样例对照);JSON字段:site_table_area_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:A区(样例对照);JSON字段:site_table_area_name';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2791960001957765(样例对照);JSON字段:tenant_table_area_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2957858167230149(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:order_pay_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2957922914357125(样例对照);JSON字段:order_settle_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:A17(样例对照);JSON字段:ledger_name';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:48.0(样例对照);JSON字段:ledger_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:3600(样例对照);JSON字段:ledger_count';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:48.0(样例对照);JSON字段:ledger_unit_price';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:1(样例对照);JSON字段:ledger_status';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2025-11-09 22:28:57(样例对照);JSON字段:ledger_start_time';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2025-11-09 23:28:57(样例对照);JSON字段:ledger_end_time';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2025-11-09 22:28:57(样例对照);JSON字段:start_use_time';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2025-11-09 23:28:57(样例对照);JSON字段:last_use_time';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:3600(样例对照);JSON字段:real_table_use_seconds';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:real_table_charge_money';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:add_clock_seconds';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:adjust_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:48.0(样例对照);JSON字段:coupon_promotion_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:member_discount_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:used_card_amount';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:mgmt_fee';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:service_money';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0.0(样例对照);JSON字段:fee_total';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:1(样例对照);JSON字段:is_single_order';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:member_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:(样例对照);JSON字段:salesman_name';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:salesman_org_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:0(样例对照);JSON字段:salesman_user_id';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '说明:同名 JSON 字段,业务含义详见 table_fee_transactions-Analysis.md;示例:2025-11-09 23:35:57(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:table_fee_transactions.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS '表用途:ODS 原始明细,对应 JSON 文件 goods_stock_movements.json,详见 goods_stock_movements-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2957911857581957(样例对照);JSON字段:siteGoodsStockId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenantId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2790685415443269(样例对照);JSON字段:siteId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2793026183532613(样例对照);JSON字段:siteGoodsId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:阿萨姆(样例对照);JSON字段:goodsName';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2790683528350539(样例对照);JSON字段:goodsCategoryId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2790683528350540(样例对照);JSON字段:goodsSecondCategoryId';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:瓶(样例对照);JSON字段:unit';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:8.0(样例对照);JSON字段:price';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:1(样例对照);JSON字段:stockType';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:-1(样例对照);JSON字段:changeNum';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:28(样例对照);JSON字段:startNum';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:27(样例对照);JSON字段:endNum';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:0(样例对照);JSON字段:changeNumA';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:0(样例对照);JSON字段:startNumA';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:0(样例对照);JSON字段:endNumA';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:(样例对照);JSON字段:remark';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operatorName';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '说明:同名 JSON 字段,业务含义详见 goods_stock_movements-Analysis.md;示例:2025-11-09 23:23:34(样例对照);JSON字段:createTime';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:goods_stock_movements.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS '表用途:ODS 原始明细,对应 JSON 文件 stock_goods_category_tree.json,详见 stock_goods_category_tree-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:2790683528350533(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:槟榔(样例对照);JSON字段:category_name';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:(样例对照);JSON字段:alias_name';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:0(样例对照);JSON字段:pid';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:槟榔(样例对照);JSON字段:business_name';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:2790683528317766(样例对照);JSON字段:tenant_goods_business_id';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:2(样例对照);JSON字段:open_salesman';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:[{"id": 2790683528350534, "tenant_id": 2790683160709957, "category_name": "槟榔…(样例对照);JSON字段:categoryBoxes';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:1(样例对照);JSON字段:sort';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '说明:同名 JSON 字段,业务含义详见 stock_goods_category_tree-Analysis.md;示例:1(样例对照);JSON字段:is_warehousing';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:stock_goods_category_tree.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS '表用途:ODS 原始明细,对应 JSON 文件 goods_stock_summary.json,详见 goods_stock_summary-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:siteGoodsId';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:goodsName';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:goodsUnit';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:goodsCategoryId';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:goodsCategorySecondId';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:categoryName';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeStartStock';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeEndStock';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeIn';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeOut';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeSale';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeSaleMoney';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:rangeInventory';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '说明:同名 JSON 字段,业务含义详见 goods_stock_summary-Analysis.md;示例:无样例(样例对照);JSON字段:currentStock';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:goods_stock_summary.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS '表用途:ODS 原始明细,对应 JSON 文件 payment_transactions.json,详见 payment_transactions-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:relate_type';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:relate_id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_amount';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_status';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_time';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:payment_method';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '说明:同名 JSON 字段,业务含义详见 payment_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:online_pay_channel';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:payment_transactions.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS '表用途:ODS 原始明细,对应 JSON 文件 refund_transactions.json,详见 refund_transactions-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:tenantName';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:relate_type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:relate_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_sn';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:refund_amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:round_amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_status';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_time';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:payment_method';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_terminal';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:pay_config_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:online_pay_channel';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:online_pay_type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:channel_fee';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:channel_payer_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:channel_pay_no';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:member_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:member_card_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:cashier_point_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:action_type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:check_status';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:is_revoke';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:balance_frozen_amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '说明:同名 JSON 字段,业务含义详见 refund_transactions-Analysis.md;示例:无样例(样例对照);JSON字段:card_frozen_amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:refund_transactions.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS '表用途:ODS 原始明细,对应 JSON 文件 platform_coupon_redemption_records.json,详见 platform_coupon_redemption_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:verify_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:certificate_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_code';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_name';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_channel';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:groupon_type';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:group_package_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:sale_price';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_money';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_free_time';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_cover';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:coupon_remark';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:use_status';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:consume_time';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:deal_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:channel_deal_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:site_order_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:table_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '说明:同名 JSON 字段,业务含义详见 platform_coupon_redemption_records-Analysis.md;示例:无样例(样例对照);JSON字段:siteProfile';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:platform_coupon_redemption_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ out_goods_id TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS '表用途:ODS 原始明细,对应 JSON 文件 tenant_goods_master.json,详见 tenant_goods_master-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2791925230096261(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:东方树叶(样例对照);JSON字段:goods_name';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:(样例对照);JSON字段:goods_bar_code';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2790683528350539(样例对照);JSON字段:goods_category_id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2790683528350540(样例对照);JSON字段:goods_second_category_id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:饮料(样例对照);JSON字段:categoryName';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:瓶(样例对照);JSON字段:unit';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:goods_number';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.out_goods_id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0(样例对照);JSON字段:out_goods_id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:goods_state';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:sale_channel';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:able_discount';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2(样例对照);JSON字段:able_site_transfer';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:is_warehousing';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:false(样例对照);JSON字段:isInSite';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0.0(样例对照);JSON字段:cost_price';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:1(样例对照);JSON字段:cost_price_type';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:8.0(样例对照);JSON字段:market_price';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0.0(样例对照);JSON字段:min_discount_price';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0(样例对照);JSON字段:common_sale_royalty';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0(样例对照);JSON字段:point_sale_royalty';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:DFSY,DFSX(样例对照);JSON字段:pinyin_initial';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:["10000028"](样例对照);JSON字段:commodityCode';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:10000028(样例对照);JSON字段:commodity_code';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(样例对照);JSON字段:goods_cover';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:0(样例对照);JSON字段:supplier_id';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:(样例对照);JSON字段:remark_name';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2025-07-15 17:13:15(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '说明:同名 JSON 字段,业务含义详见 tenant_goods_master-Analysis.md;示例:2025-10-29 23:51:38(样例对照);JSON字段:update_time';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:tenant_goods_master.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '表用途:ODS 原始明细,对应 JSON 文件 group_buy_packages.json,详见 group_buy_packages-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2939215004469573(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1814707240811572(样例对照);JSON字段:package_id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:早场特惠一小时(样例对照);JSON字段:package_name';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0.0(样例对照);JSON字段:selling_price';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0.0(样例对照);JSON字段:coupon_money';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:date_type';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:(样例对照);JSON字段:date_info';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2025-10-27 00:00:00(样例对照);JSON字段:start_time';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2026-10-28 00:00:00(样例对照);JSON字段:end_time';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:00:00:00(样例对照);JSON字段:start_clock';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1.00:00:00(样例对照);JSON字段:end_clock';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:00:00:00(样例对照);JSON字段:add_start_clock';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1.00:00:00(样例对照);JSON字段:add_end_clock';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:3600(样例对照);JSON字段:duration';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:9999999(样例对照);JSON字段:usable_count';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:(样例对照);JSON字段:usable_range';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0(样例对照);JSON字段:table_area_id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:A区(样例对照);JSON字段:table_area_name';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:(样例对照);JSON字段:table_area_id_list';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0(样例对照);JSON字段:tenant_table_area_id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2791960001957765(样例对照);JSON字段:tenant_table_area_id_list';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:site_name';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0(样例对照);JSON字段:card_type_ids';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:group_type';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:system_group_type';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2(样例对照);JSON字段:type';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:effective_status';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:is_enabled';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:0(样例对照);JSON字段:max_selectable_categories';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:1(样例对照);JSON字段:area_tag_type';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:店长:郑丽珊(样例对照);JSON字段:creator_name';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '说明:同名 JSON 字段,业务含义详见 group_buy_packages-Analysis.md;示例:2025-10-27 18:24:09(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:group_buy_packages.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS '表用途:ODS 原始明细,对应 JSON 文件 group_buy_redemption_records.json,详见 group_buy_redemption_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957924029615941(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:siteName';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2793003705192517(样例对照);JSON字段:table_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:A17(样例对照);JSON字段:tableName';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:A区(样例对照);JSON字段:tableAreaName';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2791960001957765(样例对照);JSON字段:tenant_table_area_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957858167230149(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957922914357125(样例对照);JSON字段:order_settle_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0(样例对照);JSON字段:order_pay_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957858168229573(样例对照);JSON字段:order_coupon_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:1(样例对照);JSON字段:order_coupon_channel';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0107892475999(样例对照);JSON字段:coupon_code';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:48.0(样例对照);JSON字段:coupon_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957858168229573(样例对照);JSON字段:coupon_origin_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:全天A区中八一小时(样例对照);JSON字段:ledger_name';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:(样例对照);JSON字段:ledger_group_name';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:48.0(样例对照);JSON字段:ledger_amount';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:3600(样例对照);JSON字段:ledger_count';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:29.9(样例对照);JSON字段:ledger_unit_price';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_status';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:3600(样例对照);JSON字段:table_charge_seconds';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2957858166460101(样例对照);JSON字段:promotion_activity_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2798727423528005(样例对照);JSON字段:promotion_coupon_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:3600(样例对照);JSON字段:promotion_seconds';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:1(样例对照);JSON字段:offer_type';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:assistant_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:assistant_service_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:table_service_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:goods_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:recharge_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:reward_promotion_money';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0.0(样例对照);JSON字段:goodsOptionPrice';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:(样例对照);JSON字段:salesman_name';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0(样例对照);JSON字段:sales_man_org_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_role_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_user_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:1(样例对照);JSON字段:is_single_order';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '说明:同名 JSON 字段,业务含义详见 group_buy_redemption_records-Analysis.md;示例:2025-11-09 23:35:57(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:group_buy_redemption_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS '表用途:ODS 原始明细,对应 JSON 文件 settlement_ticket_details.json,详见 settlement_ticket_details-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:2957922914357125(样例对照);JSON字段:orderSettleId';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:actualPayment';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:adjustAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:assistantManualDiscount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:balanceAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:cashierName';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:consumeMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:couponAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:deliveryAddress';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:deliveryFee';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:ledgerAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:memberDeductAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:memberOfferAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:onlineReturnAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:orderRemark';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:orderSettleNumber';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:payMemberBalance';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:payTime';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:paymentMethod';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:pointDiscountCost';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:pointDiscountPrice';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:prepayMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:refundAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:returnGoodsAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:rewardName';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:settleType';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:siteAddress';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:siteBusinessTel';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:siteId';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:siteName';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:tenantId';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:tenantName';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:ticketCustomContent';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:ticketRemark';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:voucherMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:memberProfile';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:orderItem';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '说明:同名 JSON 字段,业务含义详见 settlement_ticket_details-Analysis.md;示例:无样例(样例对照);JSON字段:tenantMemberCardLogs';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:settlement_ticket_details.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ batch_stock_quantity NUMERIC(18,2),
+ days_available INT,
+ provisional_total_cost NUMERIC(18,2),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ sort INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS '表用途:ODS 原始明细,对应 JSON 文件 store_goods_master.json,详见 store_goods_master-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2793025851560005(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:siteName';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2792178593255301(样例对照);JSON字段:tenant_goods_id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:合味道泡面(样例对照);JSON字段:goods_name';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:(样例对照);JSON字段:goods_bar_code';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2791941988405125(样例对照);JSON字段:goods_category_id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2793236829620037(样例对照);JSON字段:goods_second_category_id';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:零食(样例对照);JSON字段:oneCategoryName';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:面(样例对照);JSON字段:twoCategoryName';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:桶(样例对照);JSON字段:unit';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:12.0(样例对照);JSON字段:sale_price';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0.0(样例对照);JSON字段:cost_price';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:cost_price_type';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:7.0(样例对照);JSON字段:min_discount_price';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0(样例对照);JSON字段:safe_stock';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:18(样例对照);JSON字段:stock';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0(样例对照);JSON字段:stock_A';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:104(样例对照);JSON字段:sale_num';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0.0(样例对照);JSON字段:total_purchase_cost';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:104(样例对照);JSON字段:total_sales';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1.32(样例对照);JSON字段:average_monthly_sales';
+COMMENT ON COLUMN billiards_ods.store_goods_master.batch_stock_quantity IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:43(样例对照);JSON字段:batch_stock_quantity';
+COMMENT ON COLUMN billiards_ods.store_goods_master.days_available IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:13(样例对照);JSON字段:days_available';
+COMMENT ON COLUMN billiards_ods.store_goods_master.provisional_total_cost IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0.0(样例对照);JSON字段:provisional_total_cost';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:enable_status';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2(样例对照);JSON字段:audit_status';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:goods_state';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:is_warehousing';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:able_discount';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2(样例对照);JSON字段:able_site_transfer';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:forbid_sell_status';
+COMMENT ON COLUMN billiards_ods.store_goods_master."freeze" IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:0(样例对照);JSON字段:freeze';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:send_state';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2(样例对照);JSON字段:custom_label_type';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:option_required';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:1(样例对照);JSON字段:sale_channel';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sort IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:100(样例对照);JSON字段:sort';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:(样例对照);JSON字段:remark';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:HWDPM,GWDPM(样例对照);JSON字段:pinyin_initial';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(样例对照);JSON字段:goods_cover';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2025-07-16 11:52:51(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '说明:同名 JSON 字段,业务含义详见 store_goods_master-Analysis.md;示例:2025-11-09 07:23:47(样例对照);JSON字段:update_time';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:store_goods_master.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ ordergoodsid BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ returns_number INT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS '表用途:ODS 原始明细,对应 JSON 文件 store_goods_sales_records.json,详见 store_goods_sales_records-Analysis.md;payload 保留原始记录便于追溯。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2957924029550406(样例对照);JSON字段:id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2790683160709957(样例对照);JSON字段:tenant_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2790685415443269(样例对照);JSON字段:site_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.siteid IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:siteid';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sitename IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:朗朗桌球(样例对照);JSON字段:sitename';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2793026176012357(样例对照);JSON字段:site_goods_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2792115932417925(样例对照);JSON字段:tenant_goods_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2957922914357125(样例对照);JSON字段:order_settle_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2957858167230149(样例对照);JSON字段:order_trade_no';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2957858456391557(样例对照);JSON字段:order_goods_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ordergoodsid IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:ordergoodsid';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:order_pay_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:order_coupon_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:哇哈哈矿泉水(样例对照);JSON字段:ledger_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:酒水(样例对照);JSON字段:ledger_group_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:5.0(样例对照);JSON字段:ledger_amount';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_count';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:5.0(样例对照);JSON字段:ledger_unit_price';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:1(样例对照);JSON字段:ledger_status';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:discount_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:5.0(样例对照);JSON字段:discount_price';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:coupon_deduct_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:member_discount_amount';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:option_coupon_deduct_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:option_member_discount_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:point_discount_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:point_discount_money_cost';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:5.0(样例对照);JSON字段:real_goods_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.01(样例对照);JSON字段:cost_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:push_money';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:1(样例对照);JSON字段:sales_type';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:1(样例对照);JSON字段:is_single_order';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:is_delete';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:哇哈哈矿泉水(样例对照);JSON字段:goods_remark';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0.0(样例对照);JSON字段:option_price';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:(样例对照);JSON字段:option_value_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:无样例(样例对照);JSON字段:option_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:member_coupon_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:package_coupon_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:sales_man_org_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:(样例对照);JSON字段:salesman_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_role_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:salesman_user_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2790687322443013(样例对照);JSON字段:operator_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:收银员:郑丽珊(样例对照);JSON字段:operator_name';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2(样例对照);JSON字段:openSalesman';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.returns_number IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:0(样例对照);JSON字段:returns_number';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2793003705192517(样例对照);JSON字段:site_table_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2790683528317768(样例对照);JSON字段:tenant_goods_business_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2790683528350540(样例对照);JSON字段:tenant_goods_category_id';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '说明:同名 JSON 字段,业务含义详见 store_goods_sales_records-Analysis.md;示例:2025-11-09 23:35:57(样例对照);JSON字段:create_time';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '说明:完整原始 JSON 记录快照;示例:原文 JSON(样例对照);JSON字段:整条记录';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '说明:ETL 元数据,记录原始导出文件名;示例:store_goods_sales_records.json(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '说明:ETL 元数据,记录采集接口或下载 URL;示例:/api/xxx(样例对照);JSON字段:无(ETL元数据)';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '说明:ETL 入库时间戳;示例:2025-11-10 00:00:00+08(样例对照);JSON字段:无(ETL元数据)';
+
diff --git a/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.rewrite2.bak b/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.rewrite2.bak
new file mode 100644
index 0000000..b77de51
--- /dev/null
+++ b/tmp/etl_billiards_misc/tmp & Delete/schema_ODS_doc.sql.rewrite2.bak
@@ -0,0 +1,1945 @@
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS 'ODS 原始明细表:会员档案/会员账户信息。来源:export/test-json-doc/member_profiles.json;分析:member_profiles-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '【说明】会员的注册门店 ID。 【示例】2790685415443269(用于会员的注册门店 ID)。 【JSON字段】register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '【说明】注册门店名称,属于冗余字段,用于直接展示。 【示例】朗朗桌球(注册门店名称,属于冗余字段,用于直接展示)。 【JSON字段】site_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '【说明】这是“租户内会员账户”的主键 ID。 【示例】2955204541320325(用于这是“租户内会员账户”的主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '【说明】这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。 【示例】2955204540009605(用于这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上)。 【JSON字段】system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '【说明】这两个字段是成对出现的:一个数值码,一个中文名称。 【示例】2790683528022853(用于这两个字段是成对出现的:一个数值码,一个中文名称)。 【JSON字段】member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '【说明】这是“会员卡种类/等级”的定义字段。 【示例】储值卡(用于这是“会员卡种类/等级”的定义字段)。 【JSON字段】member_card_grade_name。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '【说明】会员绑定的手机号码。 【示例】18620043391(用于会员绑定的手机号码)。 【JSON字段】mobile。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '【说明】会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。 【示例】胡先生(用于会员在当前租户下的显示名称(可以是姓名,也可以是昵称))。 【JSON字段】nickname。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '【说明】当前积分余额(这条会员账户的积分值)。 【示例】0.0(用于当前积分余额(这条会员账户的积分值))。 【JSON字段】point。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '【说明】成长值 / 经验值,用于会员等级晋升的累计指标。 【示例】0.0(成长值 / 经验值,用于会员等级晋升的累计指标)。 【JSON字段】growth_value。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '【说明】推荐人会员 ID,用于记录该会员是由哪位老会员推荐。 【示例】0(推荐人会员 ID,用于记录该会员是由哪位老会员推荐)。 【JSON字段】referrer_member_id。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '【说明】帐户状态(偏“卡状态/档案状态”)。 【示例】1(用于帐户状态(偏“卡状态/档案状态”))。 【JSON字段】status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '【说明】用户账号状态(偏“用户逻辑”层面的状态)。 【示例】1(用于用户账号状态(偏“用户逻辑”层面的状态))。 【JSON字段】user_status。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '【说明】会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。 【示例】2025-11-08 01:29:33(用于会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_profiles.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_profiles.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS 'ODS 原始明细表:会员余额变更流水。来源:export/test-json-doc/member_balance_changes.json;分析:member_balance_changes-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '【说明】租户/商户 ID,本数据中是固定值(同一品牌/商户)。 【示例】2790683160709957(用于租户/商户 ID,本数据中是固定值(同一品牌/商户))。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '【说明】非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致)。 【示例】2790685415443269(用于非 0:记录所属的具体门店 ID(与其他 JSON 内的 site_id 一致))。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '【说明】会员卡的“注册门店 ID”,即办卡所在门店。 【示例】2790685415443269(用于会员卡的“注册门店 ID”,即办卡所在门店)。 【JSON字段】register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '【说明】卡片的注册门店名称(办卡地点),和 register_site_id 配套。 【示例】朗朗桌球(用于卡片的注册门店名称(办卡地点),和 register_site_id 配套)。 【JSON字段】registerSiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '【说明】发生本次余额变更的门店名称(即本次消费/充值所在门店)。 【示例】朗朗桌球(用于发生本次余额变更的门店名称(即本次消费/充值所在门店))。 【JSON字段】paySiteName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '【说明】余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。 【示例】2957881605869253(用于余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '【说明】商户维度的会员 ID(租户内会员主键)。 【示例】2799212845565701(用于商户维度的会员 ID(租户内会员主键))。 【JSON字段】tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '【说明】会员卡账户 ID,在租户内唯一标识某张卡。 【示例】2799219999295237(用于会员卡账户 ID,在租户内唯一标识某张卡)。 【JSON字段】tenant_member_card_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '【说明】系统级(全局)会员 ID。 【示例】2799212844549893(用于系统级(全局)会员 ID)。 【JSON字段】system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '【说明】会员姓名或称呼(非昵称字段)。 【示例】曾丹烨(用于会员姓名或称呼(非昵称字段))。 【JSON字段】memberName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '【说明】会员手机号。 【示例】13922213242(用于会员手机号)。 【JSON字段】memberMobile。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '【说明】卡种类型 ID,用于区分不同卡种。 【示例】2793249295533893(卡种类型 ID,用于区分不同卡种)。 【JSON字段】card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '【说明】卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。 【示例】储值卡(用于卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称)。 【JSON字段】memberCardTypeName。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '【说明】本次变动的金额(元),正数表示增加,负数表示减少。 【示例】-120.0(用于本次变动的金额(元),正数表示增加,负数表示减少)。 【JSON字段】account_data。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '【说明】本次变动前,该卡账户的余额(元)。 【示例】816.3(用于本次变动前,该卡账户的余额(元))。 【JSON字段】before。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '【说明】本次变动后,该卡账户的余额(元)。 【示例】696.3(用于本次变动后,该卡账户的余额(元))。 【JSON字段】after。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '【说明】可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。 【示例】0.0(可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式)。 【JSON字段】refund_amount。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】from_type。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】payment_method。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '【说明】例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。 【示例】2957881518788421(用于例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等)。 【JSON字段】relate_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '【说明】当为空时,说明这条变动没有额外备注说明。 【示例】充值退款(用于当为空时,说明这条变动没有额外备注说明)。 【JSON字段】remark。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '【说明】执行此次余额变更操作的员工 ID。 【示例】2790687322443013(用于执行此次余额变更操作的员工 ID)。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '【说明】操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。 【示例】收银员:郑丽珊(用于操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '【说明】本条余额变更记录的创建时间,通常接近交易发生时间。 【示例】2025-11-09 22:52:48(用于本条余额变更记录的创建时间,通常接近交易发生时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_balance_changes.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_balance_changes.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS 'ODS 原始明细表:会员储值/卡券账户列表。来源:export/test-json-doc/member_stored_value_cards.json;分析:member_stored_value_cards-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '【说明】租户/品牌 ID,与其他 JSON 中 tenant_id 一致。 【示例】2790683160709957(用于租户/品牌 ID,与其他 JSON 中 tenant_id 一致)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '【说明】当前商户(品牌/租户)中会员的主键 ID。 【示例】2955204541320325(用于当前商户(品牌/租户)中会员的主键 ID)。 【JSON字段】tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '【说明】系统级会员 ID(跨门店统一主键)。 【示例】2955204540009605(用于系统级会员 ID(跨门店统一主键))。 【JSON字段】system_member_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '【说明】卡首次办理的门店 ID。 【示例】2790685415443269(用于卡首次办理的门店 ID)。 【JSON字段】register_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '【说明】卡归属门店名称(视图中的展示字段)。 【示例】朗朗桌球(用于卡归属门店名称(视图中的展示字段))。 【JSON字段】site_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2955206162843781(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '【说明】卡等级/卡类代码,和下面两个名称字段一一对应。 【示例】2790683528022856(用于卡等级/卡类代码,和下面两个名称字段一一对应)。 【JSON字段】member_card_grade_code。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '【说明】卡等级/卡类名称。 【示例】活动抵用券(用于卡等级/卡类名称)。 【JSON字段】member_card_grade_code_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '【说明】卡类型名称,实际与 member_card_grade_code_name 一致。 【示例】活动抵用券(用于卡类型名称,实际与 member_card_grade_code_name 一致)。 【JSON字段】member_card_type_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '【说明】持卡会员姓名快照。 【示例】胡先生(用于持卡会员姓名快照)。 【JSON字段】member_name。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '【说明】持卡会员手机号快照。 【示例】18620043391(用于持卡会员手机号快照)。 【JSON字段】member_mobile。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '【说明】卡种 ID(定义“这是哪一种卡”)。 【示例】2793266846533445(用于卡种 ID(定义“这是哪一种卡”))。 【JSON字段】card_type_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '【说明】实体卡物理卡号/条码号。 【示例】NULL(用于实体卡物理卡号/条码号)。 【JSON字段】card_no。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '【说明】物理卡类型。 【示例】1(用于物理卡类型)。 【JSON字段】card_physics_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '【说明】当前卡内余额(主要针对储值卡、部分券卡)。 【示例】0.0(用于当前卡内余额(主要针对储值卡、部分券卡))。 【JSON字段】balance。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '【说明】采用“几折”的记法:10=不打折,9=九折,8=八折。 【示例】0.0(用于采用“几折”的记法:10=不打折,9=九折,8=八折)。 【JSON字段】denomination。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】table_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】goods_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】assistant_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】assistant_reward_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】table_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】assistant_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】coupon_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '【说明】数量/时长字段,用于统计与计量。 【示例】10.0(数量/时长字段,用于统计与计量)。 【JSON字段】goods_service_discount。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】assistant_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】table_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】goods_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '【说明】数量/时长字段,用于统计与计量。 【示例】2(数量/时长字段,用于统计与计量)。 【JSON字段】assistant_reward_discount_sub_switch。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】table_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistant_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goods_service_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistant_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】table_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goods_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】coupon_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】100.0(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistant_reward_deduct_radio。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】tableCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】tableServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】goodsCarDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】goodsServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '【说明】针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。 【示例】0.0(用于针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则))。 【JSON字段】assistantCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '【说明】如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。 【示例】0.0(用于如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置)。 【JSON字段】assistantServiceCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '【说明】助教奖励金方向扣款的配置。 【示例】0.0(用于助教奖励金方向扣款的配置)。 【JSON字段】assistantRewardCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '【说明】结算时从卡中扣除的金额上限/规则配置(视图级。 【示例】0.0(用于结算时从卡中扣除的金额上限/规则配置(视图级)。 【JSON字段】cardSettleDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '【说明】与卡绑定的“券额度扣除配置”。 【示例】0.0(用于与卡绑定的“券额度扣除配置”)。 【JSON字段】couponCardDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '【说明】配送费可否/多少从卡中抵扣,目前无业务发生。 【示例】0.0(用于配送费可否/多少从卡中抵扣,目前无业务发生)。 【JSON字段】deliveryFeeDeduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '【说明】卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。 【示例】NULL(用于卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段)。 【JSON字段】use_scene。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '【说明】是否允许跨店使用。 【示例】1(用于是否允许跨店使用)。 【JSON字段】able_cross_site。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。 【示例】NULL(布尔/开关字段,用于表示权限、可用性或状态开关)。 【JSON字段】able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '【说明】是否允许转赠/转让给其他会员。 【示例】0(用于是否允许转赠/转让给其他会员)。 【JSON字段】is_allow_give。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '【说明】是否允许在“订单层面统一扣款”。 【示例】0(用于是否允许在“订单层面统一扣款”)。 【JSON字段】is_allow_order_deduct。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '【说明】卡绑定密码,用于消费或查询验证(目前未启用)。 【示例】NULL(卡绑定密码,用于消费或查询验证(目前未启用))。 【JSON字段】bind_password。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '【说明】数量/时长字段,用于统计与计量。 【示例】1(数量/时长字段,用于统计与计量)。 【JSON字段】goods_discount_range_type。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '【说明】可用的商品分类 ID 列表。 【示例】[](用于可用的商品分类 ID 列表)。 【JSON字段】goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '【说明】限定可使用的台区 ID 列表。 【示例】[](用于限定可使用的台区 ID 列表)。 【JSON字段】tableAreaId。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '【说明】卡片限定生效门店 ID。 【示例】0(用于卡片限定生效门店 ID)。 【JSON字段】effect_site_id。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '【说明】卡片生效开始时间(有效期起始)。 【示例】2025-11-08 01:31:12(用于卡片生效开始时间(有效期起始))。 【JSON字段】start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '【说明】卡片有效期结束时间。 【示例】2225-01-01 00:00:00(用于卡片有效期结束时间)。 【JSON字段】end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】disable_start_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '【说明】停用时间段(比如临时冻结卡的起止时间)。 【示例】0001-01-01 00:00:00(用于停用时间段(比如临时冻结卡的起止时间))。 【JSON字段】disable_end_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '【说明】最近一次消费时间。 【示例】2025-11-09 07:48:23(用于最近一次消费时间)。 【JSON字段】last_consume_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '【说明】卡片创建时间(开卡时间)。 【示例】2025-11-08 01:31:12(用于卡片创建时间(开卡时间))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '【说明】状态枚举,用于标识记录当前业务状态。。 【示例】1(状态枚举,用于标识记录当前业务状态。)。 【JSON字段】status。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '【说明】在前端展示或某些列表中的排序权重。 【示例】1(用于在前端展示或某些列表中的排序权重)。 【JSON字段】sort。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '【说明】品牌头像 URL(未配置)。 【示例】NULL(用于品牌头像 URL(未配置))。 【JSON字段】tenantAvatar。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '【说明】租户/品牌名称(当前导出为空)。 【示例】NULL(用于租户/品牌名称(当前导出为空))。 【JSON字段】tenantName。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '【说明】允许使用的“陪打/助教等级”列表。 【示例】[](用于允许使用的“陪打/助教等级”列表)。 【JSON字段】pdAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '【说明】可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写)。 【示例】[](用于可能是“促销活动中的助教等级限制”(命名中 cx 多为“促销”缩写))。 【JSON字段】cxAssisnatLevel。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】member_stored_value_cards.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/member_stored_value_cards.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS 'ODS 原始明细表:充值结算记录。来源:export/test-json-doc/recharge_settlements.json;分析:recharge_settlements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tenantid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】siteid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】sitename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】balanceamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】cardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】cashamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】couponamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】createtime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】memberid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】membername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】membercardtypename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】memberphone。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tableid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】consumemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】onlineamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】operatorid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】operatorname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】revokeorderid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】revokeordername。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】revoketime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】payamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】refundamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlename。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlerelateid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlestatus。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settletype。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】paytime。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】roundingamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】paymentmethod。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】adjustamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】servicemoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】prepaymoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】salesmanname。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】orderremark。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】canberevoked。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】activitydiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】serialnumber。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isusecoupon。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】isusediscount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isactivity。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isbindmember。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isfirst。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】giftcardamount。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】recharge_settlements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/recharge_settlements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS 'ODS 原始明细表:结账/结算记录。来源:export/test-json-doc/settlement_records.json;分析:settlement_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '【说明】结账记录主键 ID(订单结算 ID)。 【示例】NULL(用于结账记录主键 ID(订单结算 ID))。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tenantid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】siteid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】sitename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】balanceamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】cardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】cashamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】couponamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】createtime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】memberid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】membername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tenantmembercardid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】membercardtypename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】memberphone。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tableid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】consumemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】onlineamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】operatorid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】operatorname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】revokeorderid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】revokeordername。';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】revoketime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】payamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】refundamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】settlename。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlerelateid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settlestatus。';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】settletype。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '【说明】时间字段,用于记录业务时间点/发生时间。 【示例】NULL(时间字段,用于记录业务时间点/发生时间)。 【JSON字段】paytime。';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】roundingamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】paymentmethod。';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】adjustamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantcxmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantpdmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】couponsaleamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】memberdiscountamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】tablechargemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】realgoodsmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】servicemoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】prepaymoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】salesmanname。';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】orderremark。';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】salesmanuserid。';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】canberevoked。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointdiscountprice。';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】pointdiscountcost。';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】activitydiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】serialnumber。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】assistantmanualdiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】allcoupondiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】goodspromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】assistantpromotionmoney。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isusecoupon。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '【说明】数量/时长字段,用于统计与计量。 【示例】NULL(数量/时长字段,用于统计与计量)。 【JSON字段】isusediscount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isactivity。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isbindmember。';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】isfirst。';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】rechargecardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。 【示例】NULL(金额字段,用于计费/结算/分摊等金额计算)。 【JSON字段】giftcardamount。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS 'ODS 原始明细表:助教作废/取消记录。来源:export/test-json-doc/assistant_cancellation_records.json;分析:assistant_cancellation_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '【说明】本表主键 ID,用于唯一标识一条记录。 【示例】2957675849518789(本表主键 ID,用于唯一标识一条记录)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '【说明】门店 ID,即该废除记录所在门店。 【示例】2790685415443269(用于门店 ID,即该废除记录所在门店)。 【JSON字段】siteId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '【说明】助教姓名/对外展示名称。 【示例】泡芙(用于助教姓名/对外展示名称)。 【JSON字段】assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '【说明】与“助教废除”关联的金额字段。 【示例】5.83(用于与“助教废除”关联的金额字段)。 【JSON字段】assistantAbolishAmount。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '【说明】助教编号(工号/序号)。 【示例】27(用于助教编号(工号/序号))。 【JSON字段】assistantOn。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '【说明】“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟。 【示例】214(用于“已发生的计费时长(分钟)”,即这次助教服务在被废除前已经累计了多少分钟)。 【JSON字段】pdChargeMinutes。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '【说明】台桌所在区域 ID。 【示例】2791963816579205(用于台桌所在区域 ID)。 【JSON字段】tableAreaId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '【说明】台桌所属区域名称。 【示例】C区(用于台桌所属区域名称)。 【JSON字段】tableArea。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '【说明】球台/桌子的 ID。 【示例】2793016660660357(用于球台/桌子的 ID)。 【JSON字段】tableId。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '【说明】台桌名称/编号,供人阅读。 【示例】C1(用于台桌名称/编号,供人阅读)。 【JSON字段】tableName。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '【说明】用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等。 【示例】NULL(用于记录“废除原因”的文本描述,例如“顾客临时有事取消”“录入错误”“更换助教”等)。 【JSON字段】trashReason。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '【说明】这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻。 【示例】2025-11-09 19:23:29(用于这条“助教废除记录”被创建的时间,即系统正式记录“废除”操作的时刻)。 【JSON字段】createTime。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_cancellation_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_cancellation_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ birth_date TIMESTAMP,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ last_update_name TEXT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS 'ODS 原始明细表:助教档案主数据。来源:export/test-json-doc/assistant_accounts_master.json;分析:assistant_accounts_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '【说明】助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。 【示例】2947562271297029(用于助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '【说明】品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。 【示例】2790683160709957(用于品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '【说明】门店 ID,对应本次数据的这家球房(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,对应本次数据的这家球房(朗朗桌球))。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '【说明】助教工号 / 编号,便于业务侧识别。 【示例】31(用于助教工号 / 编号,便于业务侧识别)。 【JSON字段】assistant_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '【说明】助教在前台展示的昵称,如“佳怡”“周周”“球球”等。 【示例】小然(用于助教在前台展示的昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '【说明】助教真实姓名,如“何海婷”“梁婷婷”等。 【示例】张静然(用于助教真实姓名,如“何海婷”“梁婷婷”等)。 【JSON字段】real_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '【说明】助教手机号,用于登录绑定、通知、钉钉同步等。 【示例】15119679931(助教手机号,用于登录绑定、通知、钉钉同步等)。 【JSON字段】mobile。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '【说明】团队名称,展示用,和 team_id 一一对应。 【示例】1组(用于团队名称,展示用,和 team_id 一一对应)。 【JSON字段】team_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '【说明】系统级“用户账号 ID”,通常对应登录账号。 【示例】2947562270838277(用于系统级“用户账号 ID”,通常对应登录账号)。 【JSON字段】user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '【说明】10 × 24。 【示例】20(用于10 × 24)。 【JSON字段】level。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '【说明】1 × 48。 【示例】1(用于1 × 48)。 【JSON字段】assistant_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '【说明】当 leave_status = 0 时,work_status = 1。 【示例】2(用于当 leave_status = 0 时,work_status = 1)。 【JSON字段】work_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '【说明】0 × 21。 【示例】1(用于0 × 21)。 【JSON字段】leave_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '【说明】入职时间。 【示例】2025-11-02 08:00:00(用于入职时间)。 【JSON字段】entry_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '【说明】离职日期。 【示例】2025-11-03 08:00:00(用于离职日期)。 【JSON字段】resign_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '【说明】当前配置生效的开始日期。 【示例】2025-11-01 08:00:00(用于当前配置生效的开始日期)。 【JSON字段】start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '【说明】当前配置生效的结束日期(例如一个周期性的排班/合同周期)。 【示例】2025-12-01 08:00:00(用于当前配置生效的结束日期(例如一个周期性的排班/合同周期))。 【JSON字段】end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '【说明】账号创建时间。 【示例】2025-11-02 15:55:26(用于账号创建时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '【说明】账号最近一次被修改的时间(例如修改等级、昵称等)。 【示例】2025-11-03 18:32:07(用于账号最近一次被修改的时间(例如修改等级、昵称等))。 【JSON字段】update_time。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '【说明】该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。 【示例】0(该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为)。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '【说明】预留给“人事系统员工 ID”的字段,目前未接入或未启用。 【示例】0(用于预留给“人事系统员工 ID”的字段,目前未接入或未启用)。 【JSON字段】staff_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '【说明】人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。 【示例】0(用于人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用)。 【JSON字段】staff_profile_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。 【示例】10(标识类 ID 字段,用于关联/定位相关实体)。 【JSON字段】system_role_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '【说明】助教头像地址。 【示例】https://oss.ficoo.vip/maUiImages/images/defaultAvatar.png(用于助教头像地址)。 【JSON字段】avatar。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.birth_date IS '【说明】助教出生日期。 【示例】0001-01-01 00:00:00(用于助教出生日期)。 【JSON字段】birth_date。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '【说明】0 × 40。 【示例】0(用于0 × 40)。 【JSON字段】gender。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '【说明】身高(单位:厘米)。 【示例】0.0(用于身高(单位:厘米))。 【JSON字段】height。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '【说明】体重(单位:公斤)。 【示例】0.0(用于体重(单位:公斤))。 【JSON字段】weight。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '【说明】备用工号字段,目前未在该门店启用。 【示例】NULL(用于备用工号字段,目前未在该门店启用)。 【JSON字段】job_num。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】show_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '【说明】前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。 【示例】31(用于前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系))。 【JSON字段】show_sort。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '【说明】评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。 【示例】0.0(评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0)。 【JSON字段】sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '【说明】助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分。 【示例】0.0(用于助教综合评分(员工维度的平均分 snapshot),当前尚未启用评分)。 【JSON字段】assistant_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '【说明】累计被评分次数。 【示例】0(用于累计被评分次数)。 【JSON字段】get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '【说明】个人简介文案,预留给助教自我介绍使用。 【示例】NULL(用于个人简介文案,预留给助教自我介绍使用)。 【JSON字段】introduce。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '【说明】助教个人视频介绍地址。 【示例】https://oss.ficoo.vip/cbb/userVideo/1753096246308/175309624630830.mp4(用于助教个人视频介绍地址)。 【JSON字段】video_introduction_url。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '【说明】上层“分组 ID”预留字段(例如集团/事业部),本门店未使用。 【示例】0(用于上层“分组 ID”预留字段(例如集团/事业部),本门店未使用)。 【JSON字段】group_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '【说明】group_id 对应的名称,目前为空。 【示例】NULL(用于group_id 对应的名称,目前为空)。 【JSON字段】group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '【说明】门店名称,冗余字段,用于展示。 【示例】朗朗桌球(门店名称,冗余字段,用于展示)。 【JSON字段】shop_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '【说明】2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现。 【示例】2(用于2 代表当前门店为“计时收费”,其他值(1、3 等)可能对应按局、按课时等,当前未出现)。 【JSON字段】charge_way。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】entry_type。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】allow_cx。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_guaranteed。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】salary_grant_enabled。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '【说明】灯光控制状态,如 1=启用控制、2=不启用 或相反。 【示例】2(用于灯光控制状态,如 1=启用控制、2=不启用 或相反)。 【JSON字段】light_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '【说明】在线状态。 【示例】1(用于在线状态)。 【JSON字段】online_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '【说明】促销时段的单价,本门店未在账号表层面设置。 【示例】0.0(用于促销时段的单价,本门店未在账号表层面设置)。 【JSON字段】cx_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '【说明】某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中)。 【示例】0.0(用于某种标准单价(例如“普通时段单价”),这里未在账号上配置(实际单价在助教商品或套餐配置中))。 【JSON字段】pd_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '【说明】该助教最近一次服务的球台 ID。 【示例】0(用于该助教最近一次服务的球台 ID)。 【JSON字段】last_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '【说明】最近服务球台名称(展示用)。 【示例】TV(用于最近服务球台名称(展示用))。 【JSON字段】last_table_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '【说明】人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织。 【示例】2947562271215109(用于人事组织 ID,通常表示“某某门店-助教部-某小组”等层级组织)。 【JSON字段】person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '【说明】系统内部生成的序列号或排序标识,用于全局排序或迁移。 【示例】0(系统内部生成的序列号或排序标识,用于全局排序或迁移)。 【JSON字段】serial_number。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_team_leader。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '【说明】1 × 49。 【示例】1(用于1 × 49)。 【JSON字段】criticism_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_update_name IS '【说明】最近修改该账号配置的管理员名称。 【示例】管理员:郑丽珊(用于最近修改该账号配置的管理员名称)。 【JSON字段】last_update_name。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】ding_talk_synced。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '【说明】门店灯控配置 ID,本门店未在助教账号维度启用。 【示例】0(用于门店灯控配置 ID,本门店未在助教账号维度启用)。 【JSON字段】site_light_cfg_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '【说明】灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件。 【示例】NULL(用于灯控设备 ID,如果开启“助教开台自动控制灯”,会通过该字段关联到灯控硬件)。 【JSON字段】light_equipment_id。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】entry_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '【说明】离职协议签署状态,类似上面。 【示例】0(用于离职协议签署状态,类似上面)。 【JSON字段】resign_sign_status。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_accounts_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_accounts_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ levelname TEXT,
+ site_assistant_id BIGINT,
+ skill_id BIGINT,
+ skillname TEXT,
+ system_member_id BIGINT,
+ tablename TEXT,
+ tenant_member_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS 'ODS 原始明细表:助教服务流水。来源:export/test-json-doc/assistant_service_records.json;分析:assistant_service_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '【说明】本条助教流水记录的主键 ID(流水唯一标识)。 【示例】2957913441292165(用于本条助教流水记录的主键 ID(流水唯一标识))。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '【说明】门店 ID,本数据中指“朗朗桌球”这一家门店。 【示例】2790685415443269(用于门店 ID,本数据中指“朗朗桌球”这一家门店)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '【说明】门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '【说明】球台 ID。 【示例】2793020259897413(用于球台 ID)。 【JSON字段】site_table_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '【说明】订单结算 ID,相当于“结账单号”的内部主键。 【示例】2957913171693253(用于订单结算 ID,相当于“结账单号”的内部主键)。 【JSON字段】order_settle_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '【说明】订单交易号,整个订单层面的编号。 【示例】2957784612605829(用于订单交易号,整个订单层面的编号)。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '【说明】关联到“支付记录”的主键 ID。 【示例】0(用于关联到“支付记录”的主键 ID)。 【JSON字段】order_pay_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '【说明】订单中“助教项目明细”的内部 ID。 【示例】2957788717240005(用于订单中“助教项目明细”的内部 ID)。 【JSON字段】order_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】order_assistant_type。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '【说明】助教姓名,如“何海婷”“胡敏”等。 【示例】何海婷(用于助教姓名,如“何海婷”“胡敏”等)。 【JSON字段】assistantName。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '【说明】助教编号,例如 "27"。 【示例】27(用于助教编号,例如 "27")。 【JSON字段】assistantNo。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '【说明】助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。 【示例】10(用于助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理))。 【JSON字段】assistant_level。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.levelname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】levelname。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_assistant_id IS '【说明】门店维度的助教 ID。 【示例】2946266869435205(用于门店维度的助教 ID)。 【JSON字段】site_assistant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_id IS '【说明】助教服务“课程/技能”ID。 【示例】2790683529513797(用于助教服务“课程/技能”ID)。 【JSON字段】skill_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skillname IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】skillname。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.system_member_id IS '【说明】系统级会员 ID(全集团统一 ID)。 【示例】0(用于系统级会员 ID(全集团统一 ID))。 【JSON字段】system_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tablename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】tablename。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_member_id IS '【说明】商户维度会员 ID(门店/品牌内的会员主键)。 【示例】0(用于商户维度会员 ID(门店/品牌内的会员主键))。 【JSON字段】tenant_member_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.user_id IS '【说明】助教对应的“用户账号 ID”(系统级用户)。 【示例】2946266868976453(用于助教对应的“用户账号 ID”(系统级用户))。 【JSON字段】user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '【说明】助教所属团队 ID。 【示例】2792011585884037(用于助教所属团队 ID)。 【JSON字段】assistant_team_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '【说明】助教对外昵称,如“佳怡”“周周”“球球”等。 【示例】泡芙(用于助教对外昵称,如“佳怡”“周周”“球球”等)。 【JSON字段】nickname。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】27-泡芙(名称字段,用于展示与辅助识别)。 【JSON字段】ledger_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '【说明】助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。 【示例】NULL(用于助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称)。 【JSON字段】ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '【说明】按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。 【示例】206.67(用于按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600))。 【JSON字段】ledger_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '【说明】台账记录的计时总秒数。 【示例】7592(用于台账记录的计时总秒数)。 【JSON字段】ledger_count。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '【说明】助教服务 标准单价(通常是标价:每小时、每节课的单价)。 【示例】98.0(用于助教服务 标准单价(通常是标价:每小时、每节课的单价))。 【JSON字段】ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】ledger_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '【说明】台账层面记录的开始时间。 【示例】2025-11-09 21:18:18(用于台账层面记录的开始时间)。 【JSON字段】ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '【说明】台账层面的结束时间。 【示例】2025-11-09 23:24:50(用于台账层面的结束时间)。 【JSON字段】ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '【说明】收银员手动给予的减免金额(人工改价)。 【示例】0.0(用于收银员手动给予的减免金额(人工改价))。 【JSON字段】manual_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '【说明】由会员卡折扣产生的优惠金额。 【示例】0.0(用于由会员卡折扣产生的优惠金额)。 【JSON字段】member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '【说明】由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。 【示例】0.0(用于由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额)。 【JSON字段】coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '【说明】用于记录与助教结算的金额(平台预留的“成本/分成”字段)。 【示例】0.0(用于记录与助教结算的金额(平台预留的“成本/分成”字段))。 【JSON字段】service_money。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '【说明】实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。 【示例】168.0(用于实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果))。 【JSON字段】projected_income。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '【说明】实际使用时长(秒)。 【示例】7592(用于实际使用时长(秒))。 【JSON字段】real_use_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '【说明】计费秒数 / 应计收入对应的时间。 【示例】7560(用于计费秒数 / 应计收入对应的时间)。 【JSON字段】income_seconds。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '【说明】助教实际开始服务时间。 【示例】2025-11-09 21:18:18(用于助教实际开始服务时间)。 【JSON字段】start_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '【说明】最后一次使用(实际服务)时间。 【示例】2025-11-09 23:24:50(用于最后一次使用(实际服务)时间)。 【JSON字段】last_use_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '【说明】这条助教流水记录创建时间(一般接近结算/下单时间)。 【示例】2025-11-09 23:25:11(用于这条助教流水记录创建时间(一般接近结算/下单时间))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_single_order。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_trash。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '【说明】废除原因(文本说明),例如“顾客取消”“录入错误”等。 【示例】NULL(用于废除原因(文本说明),例如“顾客取消”“录入错误”等)。 【JSON字段】trash_reason。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '【说明】提出废除申请的员工 ID(通常是操作员/管理员)。 【示例】0(用于提出废除申请的员工 ID(通常是操作员/管理员))。 【JSON字段】trash_applicant_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '【说明】废除申请人姓名。 【示例】NULL(用于废除申请人姓名)。 【JSON字段】trash_applicant_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '【说明】操作员 ID(录入/结算这条助教服务的员工)。 【示例】2790687322443013(用于操作员 ID(录入/结算这条助教服务的员工))。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '【说明】操作员姓名,与 operator_id 一起使用,便于直接阅读。 【示例】收银员:郑丽珊(用于操作员姓名,与 operator_id 一起使用,便于直接阅读)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '【说明】关联的“营业员/销售员姓名”,用于提成归属。 【示例】NULL(关联的“营业员/销售员姓名”,用于提成归属)。 【JSON字段】salesman_name。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '【说明】营业员用户 ID。 【示例】0(用于营业员用户 ID)。 【JSON字段】salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '【说明】助教所属“人事组织/部门 ID”。 【示例】2946266869336901(用于助教所属“人事组织/部门 ID”)。 【JSON字段】person_org_id。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '【说明】加钟秒数,即在原有预约/服务基础上临时追加的时长。 【示例】0(用于加钟秒数,即在原有预约/服务基础上临时追加的时长)。 【JSON字段】add_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '【说明】退钟秒数(取消加钟或提前结束退回的时间)。 【示例】0(用于退钟秒数(取消加钟或提前结束退回的时间))。 【JSON字段】returns_clock。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '【说明】综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。 【示例】0.0(用于综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分)。 【JSON字段】composite_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '【说明】助教服务所在的球台名称(如 "A17"、"S1")。 【示例】0001-01-01 00:00:00(用于助教服务所在的球台名称(如 "A17"、"S1"))。 【JSON字段】composite_grade_time。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '【说明】顾客对“技能表现”的评分(整数或打分等级)。 【示例】0(用于顾客对“技能表现”的评分(整数或打分等级))。 【JSON字段】skill_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '【说明】顾客对“服务态度”的评分。 【示例】0(用于顾客对“服务态度”的评分)。 【JSON字段】service_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '【说明】累计评分总和(可能用于计算平均分),当前为 0。 【示例】0.0(累计评分总和(可能用于计算平均分),当前为 0)。 【JSON字段】sum_grade。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '【说明】1 = 未评价/正常。 【示例】1(用于1 = 未评价/正常)。 【JSON字段】grade_status。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '【说明】该条记录对应的评价次数(或该助教被评价次数快照)。 【示例】0(用于该条记录对应的评价次数(或该助教被评价次数快照))。 【JSON字段】get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_not_responding。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_confirm。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】assistant_service_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/assistant_service_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS 'ODS 原始明细表:门店桌台主数据。来源:export/test-json-doc/site_tables_master.json;分析:site_tables_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '【说明】台桌主键 ID。 【示例】2791964216463493(用于台桌主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '【说明】门店名称快照,冗余字段,配合 site_id 使用。 【示例】朗朗桌球(用于门店名称快照,冗余字段,配合 site_id 使用)。 【JSON字段】siteName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '【说明】区域名称,用于前台展示和区域维度管理。 【示例】A区(区域名称,用于前台展示和区域维度管理)。 【JSON字段】areaName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '【说明】当前值:全部为 2。 【示例】2(用于当前值:全部为 2)。 【JSON字段】audit_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】charge_free。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '【说明】台桌配置的创建时间或最近一次创建/复制时间。 【示例】2025-07-15 17:52:54(用于台桌配置的创建时间或最近一次创建/复制时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '【说明】台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。 【示例】0(台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯)。 【JSON字段】delay_lights_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_online_reservation。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】is_rest_area。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】light_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '【说明】小程序二维码 URL。 【示例】2(用于小程序二维码 URL)。 【JSON字段】only_allow_groupon。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '【说明】订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。 【示例】0(用于订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费))。 【JSON字段】order_delay_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '【说明】当前值:全部为 1。 【示例】1(用于当前值:全部为 1)。 【JSON字段】self_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】show_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '【说明】门店维度的“台桌区域 ID”。 【示例】2791963794329671(用于门店维度的“台桌区域 ID”)。 【JSON字段】site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '【说明】table_status 的中文名称,仅为展示用途。 【示例】空闲中(用于table_status 的中文名称,仅为展示用途)。 【JSON字段】tableStatusName。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '【说明】台呢使用周期阈值,例如达到某个秒数后提醒更换。 【示例】0(用于台呢使用周期阈值,例如达到某个秒数后提醒更换)。 【JSON字段】table_cloth_use_Cycle。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '【说明】时间字段,用于记录业务时间点/发生时间。。 【示例】1863727(时间字段,用于记录业务时间点/发生时间。)。 【JSON字段】table_cloth_use_time。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '【说明】台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。 【示例】A1(台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段)。 【JSON字段】table_name。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '【说明】设计上应为“台的基础单价”字段(例如按小时或按局单价)。 【示例】0.0(用于设计上应为“台的基础单价”字段(例如按小时或按局单价))。 【JSON字段】table_price。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '【说明】台当前运行状态,真实反映某一时刻台的占用/暂停情况。 【示例】1(用于台当前运行状态,真实反映某一时刻台的占用/暂停情况)。 【JSON字段】table_status。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '【说明】临时点灯时长(秒),例如手动临时开灯一段时间。 【示例】0(用于临时点灯时长(秒),例如手动临时开灯一段时间)。 【JSON字段】temporary_light_second。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '【说明】当前值:全部为 0。 【示例】0(用于当前值:全部为 0)。 【JSON字段】virtual_table。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】site_tables_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/site_tables_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS 'ODS 原始明细表:台费折扣记录。来源:export/test-json-doc/table_fee_discount_records.json;分析:table_fee_discount_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '【说明】台费打折 / 调整流水主键 ID。 【示例】2957913441881989(用于台费打折 / 调整流水主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '【说明】门店 ID,本批数据全部为同一家门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本批数据全部为同一家门店(朗朗桌球))。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '【说明】门店信息快照,用于报表时直接读取,无需再联门店档案。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(门店信息快照,用于报表时直接读取,无需再联门店档案)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '【说明】台桌 ID。 【示例】2793020259897413(用于台桌 ID)。 【JSON字段】site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '【说明】折扣发生时,对应台桌的配置信息快照。 【示例】{"id": 2793020259897413, "tenant_id": 2790683160709957, "tenant_name": "", "siteName": "", "table_name": "S1", "site_ta…(用于折扣发生时,对应台桌的配置信息快照)。 【JSON字段】tableProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '【说明】租户维度的“台桌区域 ID”。 【示例】2791961347968901(用于租户维度的“台桌区域 ID”)。 【JSON字段】tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '【说明】文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。 【示例】1(用于文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型)。 【JSON字段】adjust_type。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '【说明】金额字段,用于计费/结算/分摊等金额计算。。 【示例】148.15(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '【说明】这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。 【示例】1(用于这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”)。 【JSON字段】ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '【说明】设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。 【示例】NULL(设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段)。 【JSON字段】ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '【说明】打折/调账申请人 ID。 【示例】2790687322443013(用于打折/调账申请人 ID)。 【JSON字段】applicant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '【说明】申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。 【示例】收银员:郑丽珊(用于申请人姓名(带角色描述),为 applicant_id 的冗余显示字段)。 【JSON字段】applicant_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '【说明】实际执行调账操作的操作员 ID。 【示例】2790687322443013(用于实际执行调账操作的操作员 ID)。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '【说明】操作员姓名。 【示例】收银员:郑丽珊(用于操作员姓名)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '【说明】结算单/小票 ID。 【示例】2957913171693253(用于结算单/小票 ID)。 【JSON字段】order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '【说明】订单交易号。 【示例】2957784612605829(用于订单交易号)。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '【说明】台费调整记录的创建时间,即打折操作被执行的时间戳。 【示例】2025-11-09 23:25:11(用于台费调整记录的创建时间,即打折操作被执行的时间戳)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_discount_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_discount_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS 'ODS 原始明细表:台费流水。来源:export/test-json-doc/table_fee_transactions.json;分析:table_fee_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '【说明】台费流水记录主键(事实表主键)。 【示例】2957924029058885(用于台费流水记录主键(事实表主键))。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '【说明】门店 ID,本次数据全部来自同一门店(朗朗桌球)。 【示例】2790685415443269(用于门店 ID,本次数据全部来自同一门店(朗朗桌球))。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】site_table_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '【说明】门店内“台桌区域” ID(站在门店物理布局的角度)。 【示例】2791963794329671(用于门店内“台桌区域” ID(站在门店物理布局的角度))。 【JSON字段】site_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '【说明】台桌区域的名称,用于门店表现和区域统计。 【示例】A区(台桌区域的名称,用于门店表现和区域统计)。 【JSON字段】site_table_area_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '【说明】租户维度的台桌区域 ID(品牌层面的同一类区域)。 【示例】2791960001957765(用于租户维度的台桌区域 ID(品牌层面的同一类区域))。 【JSON字段】tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '【说明】订单交易号,是整笔订单的主编号。 【示例】2957858167230149(用于订单交易号,是整笔订单的主编号)。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '【说明】订单支付记录 ID。 【示例】0(用于订单支付记录 ID)。 【JSON字段】order_pay_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '【说明】结算单号/结账 ID,对应一次结账操作。 【示例】2957922914357125(用于结算单号/结账 ID,对应一次结账操作)。 【JSON字段】order_settle_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '【说明】台号名称,实际展示给员工/顾客看的桌台编号。 【示例】A17(用于台号名称,实际展示给员工/顾客看的桌台编号)。 【JSON字段】ledger_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '【说明】按单价与计费时长计算出的原始应收台费金额。 【示例】48.0(用于按单价与计费时长计算出的原始应收台费金额)。 【JSON字段】ledger_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '【说明】台账记录的计费秒数,计费用秒数(应收时长)。 【示例】3600(用于台账记录的计费秒数,计费用秒数(应收时长))。 【JSON字段】ledger_count。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '【说明】台费结算时设置的 每小时单价/计费单价。 【示例】48.0(用于台费结算时设置的 每小时单价/计费单价)。 【JSON字段】ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】ledger_status。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '【说明】台账上的计费起始时间。 【示例】2025-11-09 22:28:57(用于台账上的计费起始时间)。 【JSON字段】ledger_start_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '【说明】台账上的计费结束时间。 【示例】2025-11-09 23:28:57(用于台账上的计费结束时间)。 【JSON字段】ledger_end_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '【说明】台开始使用的时间(实际开台时间)。 【示例】2025-11-09 22:28:57(用于台开始使用的时间(实际开台时间))。 【JSON字段】start_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '【说明】最后使用/操作时间。 【示例】2025-11-09 23:28:57(用于最后使用/操作时间)。 【JSON字段】last_use_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '【说明】实际使用的总秒数(系统真实统计的使用时长)。 【示例】3600(用于实际使用的总秒数(系统真实统计的使用时长))。 【JSON字段】real_table_use_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '【说明】台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。 【示例】0.0(用于台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分))。 【JSON字段】real_table_charge_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '【说明】加钟秒数,在原有使用基础上追加的时长。 【示例】0(用于加钟秒数,在原有使用基础上追加的时长)。 【JSON字段】add_clock_seconds。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '【说明】调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。 【示例】0.0(调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整)。 【JSON字段】adjust_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '【说明】由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。 【示例】48.0(用于由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上)。 【JSON字段】coupon_promotion_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '【说明】由会员权益产生的优惠金额,例如会员折扣、会员价等。 【示例】0.0(用于由会员权益产生的优惠金额,例如会员折扣、会员价等)。 【JSON字段】member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '【说明】由储值卡、次卡等“卡内余额”抵扣的金额。 【示例】0.0(用于由储值卡、次卡等“卡内余额”抵扣的金额)。 【JSON字段】used_card_amount。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '【说明】管理费字段,用于未来支持“台费附加管理费/服务费”的功能。 【示例】0.0(管理费字段,用于未来支持“台费附加管理费/服务费”的功能)。 【JSON字段】mgmt_fee。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '【说明】门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。 【示例】0.0(门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money)。 【JSON字段】service_money。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '【说明】各种附加费用(如管理费、服务费)合计值。 【示例】0.0(用于各种附加费用(如管理费、服务费)合计值)。 【JSON字段】fee_total。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】1(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_single_order。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '【说明】门店/租户内的会员 ID。 【示例】0(用于门店/租户内的会员 ID)。 【JSON字段】member_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '【说明】操作员 ID,负责开台/结账的员工账号 ID。 【示例】2790687322443013(用于操作员 ID,负责开台/结账的员工账号 ID)。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '【说明】操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。 【示例】收银员:郑丽珊(用于操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '【说明】业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。 【示例】NULL(用于业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人)。 【JSON字段】salesman_name。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '【说明】营业员所属机构/部门 ID。 【示例】0(用于营业员所属机构/部门 ID)。 【JSON字段】salesman_org_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '【说明】营业员的用户 ID(与 salesman_name 搭配)。 【示例】0(用于营业员的用户 ID(与 salesman_name 搭配))。 【JSON字段】salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '【说明】这条台费流水记录的创建时间,通常接近结账时间。 【示例】2025-11-09 23:35:57(用于这条台费流水记录的创建时间,通常接近结账时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】table_fee_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/table_fee_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS 'ODS 原始明细表:商品库存变动流水。来源:export/test-json-doc/goods_stock_movements.json;分析:goods_stock_movements-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '【说明】门店某个“商品库存记录”的主键 ID。 【示例】2957911857581957(用于门店某个“商品库存记录”的主键 ID)。 【JSON字段】siteGoodsStockId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenantId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】siteId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '【说明】门店维度的商品 ID。 【示例】2793026183532613(用于门店维度的商品 ID)。 【JSON字段】siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '【说明】商品名称。 【示例】阿萨姆(用于商品名称)。 【JSON字段】goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】goodsSecondCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '【说明】库存计量单位。 【示例】瓶(用于库存计量单位)。 【JSON字段】unit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '【说明】商品单价(单位金额)。 【示例】8.0(用于商品单价(单位金额))。 【JSON字段】price。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '【说明】1:89 条。 【示例】1(用于1:89 条)。 【JSON字段】stockType。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '【说明】本次库存数量变化值。 【示例】-1(用于本次库存数量变化值)。 【JSON字段】changeNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '【说明】变动前(这次出入库之前)的库存数量。 【示例】28(用于变动前(这次出入库之前)的库存数量)。 【JSON字段】startNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '【说明】变动后(出入库之后)的库存数量。 【示例】27(用于变动后(出入库之后)的库存数量)。 【JSON字段】endNum。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '【说明】辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。 【示例】0(用于辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用)。 【JSON字段】changeNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '【说明】辅助计量单位的起始库存(例如件/箱等第二单位)。 【示例】0(用于辅助计量单位的起始库存(例如件/箱等第二单位))。 【JSON字段】startNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '【说明】辅助单位的变动后库存,同样未启用。 【示例】0(用于辅助单位的变动后库存,同样未启用)。 【JSON字段】endNumA。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '【说明】备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。 【示例】NULL(备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”))。 【JSON字段】remark。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '【说明】执行此次库存变动的操作人。 【示例】收银员:郑丽珊(用于执行此次库存变动的操作人)。 【JSON字段】operatorName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '【说明】这条库存变动记录的创建时间,即发生库存变更的时间点。 【示例】2025-11-09 23:23:34(用于这条库存变动记录的创建时间,即发生库存变更的时间点)。 【JSON字段】createTime。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_movements.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_movements.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS 'ODS 原始明细表:商品分类树。来源:export/test-json-doc/stock_goods_category_tree.json;分析:stock_goods_category_tree-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '【说明】分类节点主键 ID(在商品分类维度中的唯一标识)。 【示例】2790683528350533(用于分类节点主键 ID(在商品分类维度中的唯一标识))。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '【说明】分类名称(实际业务分类名称)。 【示例】槟榔(用于分类名称(实际业务分类名称))。 【JSON字段】category_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '【说明】名称字段,用于展示与辅助识别。。 【示例】NULL(名称字段,用于展示与辅助识别。)。 【JSON字段】alias_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '【说明】父级分类 ID。 【示例】0(用于父级分类 ID)。 【JSON字段】pid。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '【说明】业务大类名称。 【示例】槟榔(用于业务大类名称)。 【JSON字段】business_name。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '【说明】业务大类 ID。 【示例】2790683528317766(用于业务大类 ID)。 【JSON字段】tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '【说明】是否启用“营业员”或“导购提成”相关的功能开关。 【示例】2(用于是否启用“营业员”或“导购提成”相关的功能开关)。 【JSON字段】open_salesman。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '【说明】子分类数组。 【示例】[{"id": 2790683528350534, "tenant_id": 2790683160709957, "category_name": "槟榔", "alias_name": "", "pid": 27906835283505…(用于子分类数组)。 【JSON字段】categoryBoxes。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '【说明】分类的排序序号,用于前端展示顺序的控制。 【示例】1(分类的排序序号,用于前端展示顺序的控制)。 【JSON字段】sort。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '【说明】本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1。 【示例】1(用于本文件可视为“所有参与库存管理的商品分类清单”,因此均为 1)。 【JSON字段】is_warehousing。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】stock_goods_category_tree.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/stock_goods_category_tree.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS 'ODS 原始明细表:商品库存汇总。来源:export/test-json-doc/goods_stock_summary.json;分析:goods_stock_summary-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '【说明】门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识。 【示例】2791953867886725(用于门店商品 ID,本库存汇总表的主键,对应某个具体商品在本店的唯一标识)。 【JSON字段】siteGoodsId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '【说明】商品名称,冗余于门店商品档案的 goods_name。 【示例】东方树叶(用于商品名称,冗余于门店商品档案的 goods_name)。 【JSON字段】goodsName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '【说明】商品的计量单位(售卖单位)。 【示例】瓶(用于商品的计量单位(售卖单位))。 【JSON字段】goodsUnit。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '【说明】一级商品分类 ID。 【示例】2790683528350539(用于一级商品分类 ID)。 【JSON字段】goodsCategoryId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '【说明】二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类。 【示例】2790683528350540(用于二级(次级)商品分类 ID,是 goodsCategoryId 的下级分类)。 【JSON字段】goodsCategorySecondId。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '【说明】一级分类名称,属于冗余字段,用于直接展示。 【示例】酒水(一级分类名称,属于冗余字段,用于直接展示)。 【JSON字段】categoryName。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '【说明】查询区间 起始时刻 的库存数量(期初库存)。 【示例】165(用于查询区间 起始时刻 的库存数量(期初库存))。 【JSON字段】rangeStartStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '【说明】查询区间 结束时刻 的库存数量(期末库存)。 【示例】118(用于查询区间 结束时刻 的库存数量(期末库存))。 【JSON字段】rangeEndStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '【说明】查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等。 【示例】450(用于查询区间内的 入库数量汇总(正值),包括采购入库、调拨入库等)。 【JSON字段】rangeIn。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '【说明】查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售)。 【示例】-497(用于查询区间内的 出库数量汇总,以 负数 表示从库存扣减(出库/销售))。 【JSON字段】rangeOut。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '【说明】查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等)。 【示例】488(用于查询区间内,该商品的 销售数量汇总(售出多少“包/瓶/份”等))。 【JSON字段】rangeSale。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '【说明】查询区间内,该商品销售的 金额小计(按商品维度汇总)。 【示例】3904.0(用于查询区间内,该商品销售的 金额小计(按商品维度汇总))。 【JSON字段】rangeSaleMoney。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '【说明】查询区间内的 盘点调整净变动量(盘盈–盘亏)。 【示例】0(用于查询区间内的 盘点调整净变动量(盘盈–盘亏))。 【JSON字段】rangeInventory。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '【说明】导出时刻的实时库存数量。 【示例】118(用于导出时刻的实时库存数量)。 【JSON字段】currentStock。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】goods_stock_summary.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/goods_stock_summary.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS 'ODS 原始明细表:支付流水。来源:export/test-json-doc/payment_transactions.json;分析:payment_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '【说明】支付流水记录的主键 ID。 【示例】2957924026486597(用于支付流水记录的主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '【说明】支付记录所属的门店 ID。 【示例】2790685415443269(用于支付记录所属的门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '【说明】门店信息快照,与其他 JSON 中的 siteProfile 结构一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,与其他 JSON 中的 siteProfile 结构一致)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '【说明】表示“这条支付记录关联的业务类型”。 【示例】2(用于表示“这条支付记录关联的业务类型”)。 【JSON字段】relate_type。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '【说明】关联业务记录的主键 ID(按 relate_type 不同指向不同表)。 【示例】2957922914357125(用于关联业务记录的主键 ID(按 relate_type 不同指向不同表))。 【JSON字段】relate_id。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '【说明】本条支付流水的“支付金额”,单位为元。 【示例】10.0(用于本条支付流水的“支付金额”,单位为元)。 【JSON字段】pay_amount。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '【说明】支付状态枚举字段。 【示例】2(用于支付状态枚举字段)。 【JSON字段】pay_status。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '【说明】实际支付完成时间(支付状态变为成功的时间戳)。 【示例】2025-11-09 23:35:57(用于实际支付完成时间(支付状态变为成功的时间戳))。 【JSON字段】pay_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '【说明】支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳)。 【示例】2025-11-09 23:35:57(用于支付记录创建时间,通常与发起支付请求的时间一致(创建支付流水的时间戳))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '【说明】支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种。 【示例】4(用于支付方式枚举,例如微信、支付宝、现金、银行卡、储值卡等某一种)。 【JSON字段】payment_method。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '【说明】每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一)。 【示例】0(用于每一笔结账单(settleList.id)对应一条支付记录(当前样本中是一条记录,relate_id 唯一))。 【JSON字段】online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】payment_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/payment_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS 'ODS 原始明细表:退款流水。来源:export/test-json-doc/refund_transactions.json;分析:refund_transactions-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '【说明】本条 退款流水 的唯一 ID。 【示例】2955202296416389(用于本条 退款流水 的唯一 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '【说明】租户/品牌 ID,全系统维度标识该商户。 【示例】2790683160709957(用于租户/品牌 ID,全系统维度标识该商户)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '【说明】租户(商户)名称。 【示例】朗朗桌球(用于租户(商户)名称)。 【JSON字段】tenantName。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '【说明】门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '【说明】本退款对应的“业务类型”。 【示例】5(用于本退款对应的“业务类型”)。 【JSON字段】relate_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '【说明】本次退款关联的业务 ID。 【示例】2955078219057349(用于本次退款关联的业务 ID)。 【JSON字段】relate_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】pay_sn。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '【说明】本次退款的 资金变动金额。 【示例】-5000.0(用于本次退款的 资金变动金额)。 【JSON字段】pay_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '【说明】设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用。 【示例】0.0(用于设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用)。 【JSON字段】refund_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '【说明】舍入金额/抹零金额。 【示例】0.0(用于舍入金额/抹零金额)。 【JSON字段】round_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】pay_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '【说明】退款在支付渠道层面实际发生的时间。 【示例】2025-11-08 01:27:16(用于退款在支付渠道层面实际发生的时间)。 【JSON字段】pay_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '【说明】本条退款流水在系统内创建时间。 【示例】2025-11-08 01:27:16(用于本条退款流水在系统内创建时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】4(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】payment_method。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】pay_terminal。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '【说明】支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。 【示例】0(用于支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键)。 【JSON字段】pay_config_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】online_pay_channel。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '【说明】当前:全部 0。 【示例】0(用于当前:全部 0)。 【JSON字段】online_pay_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '【说明】第三方支付渠道对本次退款收取的手续费。 【示例】0.0(用于第三方支付渠道对本次退款收取的手续费)。 【JSON字段】channel_fee。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '【说明】支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。 【示例】NULL(用于支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等)。 【JSON字段】channel_payer_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '【说明】第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。 【示例】NULL(用于第三方支付平台的交易号(如微信支付单号、支付宝交易号等))。 【JSON字段】channel_pay_no。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '【说明】租户内部的会员 ID(对应会员档案中的某个主键)。 【示例】0(用于租户内部的会员 ID(对应会员档案中的某个主键))。 【JSON字段】member_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '【说明】关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。 【示例】0(用于关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡))。 【JSON字段】member_card_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '【说明】收银点 ID,例如前台 1、前台 2、自助机等。 【示例】0(用于收银点 ID,例如前台 1、前台 2、自助机等)。 【JSON字段】cashier_point_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '【说明】执行该退款操作的操作员 ID。 【示例】0(用于执行该退款操作的操作员 ID)。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '【说明】当前:全部 2。 【示例】2(用于当前:全部 2)。 【JSON字段】action_type。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '【说明】当前:全部 1。 【示例】1(用于当前:全部 1)。 【JSON字段】check_status。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】0(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】is_revoke。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '【说明】涉及会员储值卡退款时,暂时冻结的余额金额。 【示例】0.0(用于涉及会员储值卡退款时,暂时冻结的余额金额)。 【JSON字段】balance_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '【说明】与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。 【示例】0.0(用于与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关)。 【JSON字段】card_frozen_amount。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】refund_transactions.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/refund_transactions.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS 'ODS 原始明细表:平台券核销/使用记录。来源:export/test-json-doc/platform_coupon_redemption_records.json;分析:platform_coupon_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '【说明】本条平台验券记录在本系统内的主键 ID。 【示例】2957929042218501(用于本条平台验券记录在本系统内的主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '【说明】平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID)。 【示例】7570689090418149418(用于平台核销记录 ID(某些平台会为每一次核销生成一个唯一 ID))。 【JSON字段】verify_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '【说明】平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID)。 【示例】5008024789379597447(用于平台侧的凭证 ID(通常由第三方团购平台生成的券实例 ID))。 【JSON字段】certificate_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '【说明】券码,顾客出示的团购券密码/编号。 【示例】0102701209726(用于券码,顾客出示的团购券密码/编号)。 【JSON字段】coupon_code。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '【说明】团购券产品名称(即第三方平台上向顾客展示的名称)。 【示例】【全天可用】中八桌球一小时(A区)(用于团购券产品名称(即第三方平台上向顾客展示的名称))。 【JSON字段】coupon_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '【说明】券来源渠道(第三方平台渠道编号)。 【示例】1(用于券来源渠道(第三方平台渠道编号))。 【JSON字段】coupon_channel。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '【说明】团购券类型。 【示例】1(用于团购券类型)。 【JSON字段】groupon_type。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '【说明】标识类 ID 字段,用于关联/定位相关实体。。 【示例】0(标识类 ID 字段,用于关联/定位相关实体。)。 【JSON字段】group_package_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '【说明】顾客在第三方平台上实际支付的价格(团购售价)。 【示例】29.9(用于顾客在第三方平台上实际支付的价格(团购售价))。 【JSON字段】sale_price。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '【说明】券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”)。 【示例】48.0(用于券面值 / 套餐价值(系统层面的“可抵扣金额或对应套餐价值”))。 【JSON字段】coupon_money。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '【说明】券附带的“免费时长”字段(例如送多少分钟台费)。 【示例】0(用于券附带的“免费时长”字段(例如送多少分钟台费))。 【JSON字段】coupon_free_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】coupon_cover。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】617547ec-9697-4f58-a700-b30a49e88904||CgYIASAHKAESLgos9ZhHDryhHb0z3RpdBZ0dVoaQbkldBcx/XTXPV8Te+9SEqYOa7aDp8nbKOpsaAA==(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】coupon_remark。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '【说明】值 1:198 条。 【示例】1(用于值 1:198 条)。 【JSON字段】use_status。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '【说明】券被核销/使用的业务时间。 【示例】2025-11-09 23:41:04(用于券被核销/使用的业务时间)。 【JSON字段】consume_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '【说明】验券记录在本系统中创建的时间(记录入库时间)。 【示例】2025-11-09 23:41:03(用于验券记录在本系统中创建的时间(记录入库时间))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '【说明】另一个层次的团购产品 ID。 【示例】1345108507(用于另一个层次的团购产品 ID)。 【JSON字段】deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '【说明】渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键。 【示例】1128411555(用于渠道侧 dealId / 产品 ID,一般是第三方平台给该团购商品定义的主键)。 【JSON字段】channel_deal_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '【说明】门店内部的订单 ID(平台券核销时对应的店内订单)。 【示例】2957929043037702(用于门店内部的订单 ID(平台券核销时对应的店内订单))。 【JSON字段】site_order_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '【说明】使用券的球台 ID。 【示例】2793001904918661(用于使用券的球台 ID)。 【JSON字段】table_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '【说明】商户/租户 ID(品牌级别)。 【示例】2790683160709957(用于商户/租户 ID(品牌级别))。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '【说明】操作员 ID(执行验券操作的收银员/员工)。 【示例】2790687322443013(用于操作员 ID(执行验券操作的收银员/员工))。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '【说明】操作员姓名,例如 "收银员:郑丽珊"。 【示例】收银员:郑丽珊(用于操作员姓名,例如 "收银员:郑丽珊")。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '【说明】把平台验券记录挂到本门店的一条订单上。 【示例】0(用于把平台验券记录挂到本门店的一条订单上)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '【说明】门店信息快照。 【示例】{"id": 2790685415443269, "org_id": 2790684179467077, "shop_name": "朗朗桌球", "avatar": "https://oss.ficoo.vip/admin/hXcE4E…(用于门店信息快照)。 【JSON字段】siteProfile。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】platform_coupon_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/platform_coupon_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ out_goods_id TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS 'ODS 原始明细表:租户商品主数据。来源:export/test-json-doc/tenant_goods_master.json;分析:tenant_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '【说明】商品档案主键 ID,唯一标识一条商品。 【示例】2791925230096261(用于商品档案主键 ID,唯一标识一条商品)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '【说明】商品名称(前台展示名称)。 【示例】东方树叶(用于商品名称(前台展示名称))。 【JSON字段】goods_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '【说明】商品条码(EAN 等),目前未维护。 【示例】NULL(用于商品条码(EAN 等),目前未维护)。 【JSON字段】goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2790683528350539(用于商品一级分类 ID)。 【JSON字段】goods_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2790683528350540(用于商品二级分类 ID)。 【JSON字段】goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '【说明】商品一级分类名称(业务可读)。 【示例】饮料(用于商品一级分类名称(业务可读))。 【JSON字段】categoryName。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '【说明】计量单位。 【示例】瓶(用于计量单位)。 【JSON字段】unit。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '【说明】商品内部编码(自定义货号/系统货号)。 【示例】1(用于商品内部编码(自定义货号/系统货号))。 【JSON字段】goods_number。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.out_goods_id IS '【说明】外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等)。 【示例】0(用于外部系统商品 ID(对接第三方平台使用,如外卖、线上商城等))。 【JSON字段】out_goods_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '【说明】商品状态(上架/下架等)。 【示例】1(用于商品状态(上架/下架等))。 【JSON字段】goods_state。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '【说明】销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。 【示例】1(用于销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码)。 【JSON字段】sale_channel。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '【说明】是否允许参与折扣/打折。 【示例】1(用于是否允许参与折扣/打折)。 【JSON字段】able_discount。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '【说明】布尔/开关字段,用于表示权限、可用性或状态开关。。 【示例】2(布尔/开关字段,用于表示权限、可用性或状态开关。)。 【JSON字段】able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '【说明】是否启用库存管理。 【示例】1(用于是否启用库存管理)。 【JSON字段】is_warehousing。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '【说明】是否在当前门店启用/上架。 【示例】false(用于是否在当前门店启用/上架)。 【JSON字段】isInSite。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '【说明】成本价格。 【示例】0.0(用于成本价格)。 【JSON字段】cost_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '【说明】金额字段,用于计费/结算/分摊等金额计算。。 【示例】1(金额字段,用于计费/结算/分摊等金额计算。)。 【JSON字段】cost_price_type。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '【说明】商品标价 / 售价(标准销售单价)。 【示例】8.0(用于商品标价 / 售价(标准销售单价))。 【JSON字段】market_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '【说明】该商品允许售卖的最低价格(底价)。 【示例】0.0(用于该商品允许售卖的最低价格(底价))。 【JSON字段】min_discount_price。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '【说明】普通销售提成比例或提成金额的配置字段。 【示例】0(用于普通销售提成比例或提成金额的配置字段)。 【JSON字段】common_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '【说明】积分销售提成/积分赠送规则相关配置。 【示例】0(用于积分销售提成/积分赠送规则相关配置)。 【JSON字段】point_sale_royalty。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '【说明】拼音首字母/助记码。 【示例】DFSY,DFSX(用于拼音首字母/助记码)。 【JSON字段】pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '【说明】与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。 【示例】["10000028"](用于与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景)。 【JSON字段】commodityCode。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '【说明】商品编码(通常为对外商品编码或条码)。 【示例】10000028(用于商品编码(通常为对外商品编码或条码))。 【JSON字段】commodity_code。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '【说明】商品封面图片 URL 地址。 【示例】https://oss.ficoo.vip/admin/ZwS8fj_1753175129443.jpg(用于商品封面图片 URL 地址)。 【JSON字段】goods_cover。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '【说明】供应商 ID,用于关联到供应商档案。 【示例】0(供应商 ID,用于关联到供应商档案)。 【JSON字段】supplier_id。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '【说明】商品备注名/别名,通常用来配置简写或特殊显示名称。 【示例】NULL(用于商品备注名/别名,通常用来配置简写或特殊显示名称)。 【JSON字段】remark_name。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '【说明】商品档案创建时间。 【示例】2025-07-15 17:13:15(用于商品档案创建时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '【说明】商品档案最近一次修改时间。 【示例】2025-10-29 23:51:38(用于商品档案最近一次修改时间)。 【JSON字段】update_time。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】tenant_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/tenant_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS 'ODS 原始明细表:团购套餐主数据。来源:export/test-json-doc/group_buy_packages.json;分析:group_buy_packages-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '【说明】门店侧套餐 ID,本文件内部的主键。 【示例】2939215004469573(用于门店侧套餐 ID,本文件内部的主键)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '【说明】“上层套餐 ID” 或“总部/系统级套餐 ID”。 【示例】1814707240811572(用于“上层套餐 ID” 或“总部/系统级套餐 ID”)。 【JSON字段】package_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '【说明】团购套餐名称,用于前台展示和核销界面。 【示例】早场特惠一小时(团购套餐名称,用于前台展示和核销界面)。 【JSON字段】package_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '【说明】语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。 【示例】0.0(用于语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格))。 【JSON字段】selling_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '【说明】券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。 【示例】0.0(用于券面值或内部结算面值,表示该套餐在门店侧对应的金额额度)。 【JSON字段】coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】date_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '【说明】预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。 【示例】0(用于预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码))。 【JSON字段】date_info。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '【说明】套餐开始生效的日期时间。 【示例】2025-10-27 00:00:00(用于套餐开始生效的日期时间)。 【JSON字段】start_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '【说明】套餐失效的日期时间(到这个时间点后不可使用)。 【示例】2026-10-28 00:00:00(用于套餐失效的日期时间(到这个时间点后不可使用))。 【JSON字段】end_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '【说明】每日可用起始时间点(第一段)。 【示例】00:00:00(用于每日可用起始时间点(第一段))。 【JSON字段】start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '【说明】每日可用的结束时间点(第一段)。 【示例】1.00:00:00(用于每日可用的结束时间点(第一段))。 【JSON字段】end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '【说明】附加可用时间段的起始时间(第二段)。 【示例】00:00:00(用于附加可用时间段的起始时间(第二段))。 【JSON字段】add_start_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '【说明】附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。 【示例】1.00:00:00(用于附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用)。 【JSON字段】add_end_clock。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '【说明】套餐内包含的时长(秒)。 【示例】3600(用于套餐内包含的时长(秒))。 【JSON字段】duration。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '【说明】可使用次数上限。 【示例】9999999(用于可使用次数上限)。 【JSON字段】usable_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '【说明】一般用于文字描述可用日期范围(例如“周一至周五”)。 【示例】NULL(一般用于文字描述可用日期范围(例如“周一至周五”))。 【JSON字段】usable_range。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '【说明】原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。 【示例】0(用于原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储)。 【JSON字段】table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '【说明】套餐适用的“门店台区名称”,用于显示和筛选。 【示例】A区(套餐适用的“门店台区名称”,用于显示和筛选)。 【JSON字段】table_area_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '【说明】用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。 【示例】NULL(用于用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制)。 【JSON字段】table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '【说明】与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。 【示例】0(与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择)。 【JSON字段】tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '【说明】实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。 【示例】2791960001957765(用于实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围)。 【JSON字段】tenant_table_area_id_list。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '【说明】门店名称。 【示例】朗朗桌球(用于门店名称)。 【JSON字段】site_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '【说明】租户 ID(品牌/商户 ID)。 【示例】2790683160709957(用于租户 ID(品牌/商户 ID))。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '【说明】原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。 【示例】0(用于原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置)。 【JSON字段】card_type_ids。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】system_group_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '【说明】内部业务子类型,具体含义需要结合系统文档。 【示例】2(用于内部业务子类型,具体含义需要结合系统文档)。 【JSON字段】type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '【说明】1:13 条。 【示例】1(用于1:13 条)。 【JSON字段】effective_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '【说明】启用状态。 【示例】1(用于启用状态)。 【JSON字段】is_enabled。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】0(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】max_selectable_categories。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '【说明】1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。 【示例】1(用于1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等)。 【JSON字段】area_tag_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '【说明】创建人信息,一般包含“角色:姓名”。 【示例】店长:郑丽珊(用于创建人信息,一般包含“角色:姓名”)。 【JSON字段】creator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '【说明】该套餐在系统中创建的时间。 【示例】2025-10-27 18:24:09(用于该套餐在系统中创建的时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_packages.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_packages.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS 'ODS 原始明细表:团购核销记录。来源:export/test-json-doc/group_buy_redemption_records.json;分析:group_buy_redemption_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '【说明】本条“团购套餐流水”记录的 主键 ID。 【示例】2957924029615941(用于本条“团购套餐流水”记录的 主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '【说明】门店 ID,与其它 JSON 中一致。 【示例】2790685415443269(用于门店 ID,与其它 JSON 中一致)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '【说明】门店名称,冗余展示用。 【示例】朗朗桌球(用于门店名称,冗余展示用)。 【JSON字段】siteName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】table_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '【说明】本次使用券所关联的 球台名称/台号。 【示例】A17(用于本次使用券所关联的 球台名称/台号)。 【JSON字段】tableName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '【说明】该球台所属的 台区名称。 【示例】A区(用于该球台所属的 台区名称)。 【JSON字段】tableAreaName。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '【说明】租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。 【示例】2791960001957765(用于租户级台区分组 ID,表示当前使用券的台桌所属的区域组合)。 【JSON字段】tenant_table_area_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '【说明】订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。 【示例】2957858167230149(用于订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键)。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '【说明】结算单 ID(小票结账主键)。 【示例】2957922914357125(用于结算单 ID(小票结账主键))。 【JSON字段】order_settle_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '【说明】指向支付记录表中的支付流水 ID。 【示例】0(用于指向支付记录表中的支付流水 ID)。 【JSON字段】order_pay_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '【说明】订单中“券使用记录”的 ID。 【示例】2957858168229573(用于订单中“券使用记录”的 ID)。 【JSON字段】order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】order_coupon_channel。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '【说明】团购券券码,核销时扫描/录入的字符串。 【示例】0107892475999(用于团购券券码,核销时扫描/录入的字符串)。 【JSON字段】coupon_code。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '【说明】本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。 【示例】48.0(用于本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”))。 【JSON字段】coupon_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '【说明】平台/上游系统中的券记录主键 ID,“券来源 ID”。 【示例】2957858168229573(用于平台/上游系统中的券记录主键 ID,“券来源 ID”)。 【JSON字段】coupon_origin_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '【说明】台费侧关联的“团购项目名称”(记账名)。 【示例】全天A区中八一小时(用于台费侧关联的“团购项目名称”(记账名))。 【JSON字段】ledger_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '【说明】团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。 【示例】NULL(用于团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等))。 【JSON字段】ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '【说明】本次券实际冲抵台费的金额。 【示例】48.0(用于本次券实际冲抵台费的金额)。 【JSON字段】ledger_amount。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '【说明】按此次优惠实际计算的“核销秒数”。 【示例】3600(用于按此次优惠实际计算的“核销秒数”)。 【JSON字段】ledger_count。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '【说明】对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。 【示例】29.9(用于对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价))。 【JSON字段】ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '【说明】流水状态。 【示例】1(用于流水状态)。 【JSON字段】ledger_status。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '【说明】本次结算中该球台总计计费的秒数(整台的台费计费时间)。 【示例】3600(用于本次结算中该球台总计计费的秒数(整台的台费计费时间))。 【JSON字段】table_charge_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '【说明】团购/促销活动 ID。 【示例】2957858166460101(用于团购/促销活动 ID)。 【JSON字段】promotion_activity_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '【说明】团购套餐定义 ID。 【示例】2798727423528005(用于团购套餐定义 ID)。 【JSON字段】promotion_coupon_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '【说明】团购套餐定义的“标准时长”(券本身标称的可用时长)。 【示例】3600(用于团购套餐定义的“标准时长”(券本身标称的可用时长))。 【JSON字段】promotion_seconds。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '【说明】优惠类型。 【示例】1(用于优惠类型)。 【JSON字段】offer_type。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '【说明】分摊到“助教服务”的促销金额。 【示例】0.0(用于分摊到“助教服务”的促销金额)。 【JSON字段】assistant_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '【说明】进一步细分助教服务的促销金额。 【示例】0.0(用于进一步细分助教服务的促销金额)。 【JSON字段】assistant_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '【说明】本次券使用中,分摊到“台费服务费”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“台费服务费”部分的促销金额)。 【JSON字段】table_service_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '【说明】本次券使用中,分摊到“商品”部分的促销金额。 【示例】0.0(用于本次券使用中,分摊到“商品”部分的促销金额)。 【JSON字段】goods_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '【说明】来自“充值类优惠”的分摊金额(例如储值赠送部分)。 【示例】0.0(用于来自“充值类优惠”的分摊金额(例如储值赠送部分))。 【JSON字段】recharge_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '【说明】本次促销中,属于“奖励金/积分抵扣”的金额。 【示例】0.0(用于本次促销中,属于“奖励金/积分抵扣”的金额)。 【JSON字段】reward_promotion_money。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '【说明】商品规格价格,用于商品类促销分摊时使用。 【示例】0.0(商品规格价格,用于商品类促销分摊时使用)。 【JSON字段】goodsOptionPrice。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '【说明】营业员姓名。 【示例】NULL(用于营业员姓名)。 【JSON字段】salesman_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '【说明】营业员所属组织 ID。 【示例】0(用于营业员所属组织 ID)。 【JSON字段】sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '【说明】营业员角色 ID。 【示例】0(用于营业员角色 ID)。 【JSON字段】salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '【说明】营业员/业务员用户 ID。 【示例】0(用于营业员/业务员用户 ID)。 【JSON字段】salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '【说明】执行本次核销/结算操作的 操作员 ID。 【示例】2790687322443013(用于执行本次核销/结算操作的 操作员 ID)。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '【说明】操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。 【示例】收银员:郑丽珊(用于操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '【说明】是否单独作为一条订单行。 【示例】1(用于是否单独作为一条订单行)。 【JSON字段】is_single_order。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '【说明】逻辑删除标记(0=否,1=是)。。 【示例】0(用于逻辑删除标记(0=否,1=是))。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '【说明】本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。 【示例】2025-11-09 23:35:57(用于本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】group_buy_redemption_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/group_buy_redemption_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS 'ODS 原始明细表:结算小票明细。来源:export/test-json-doc/settlement_ticket_details.json;分析:settlement_ticket_details-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '【说明】结算单 ID(和顶层字段相同,再次冗余)。 【示例】2957922914357125(用于结算单 ID(和顶层字段相同,再次冗余))。 【JSON字段】orderSettleId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '【说明】本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。 【示例】NULL(用于本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等))。 【JSON字段】actualPayment。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '【说明】人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计。 【示例】NULL(用于人工调价/整单调整金额(例如手工改价、折扣调整),是所有类型的手工调整合计)。 【JSON字段】adjustAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '【说明】针对“助教项目”的人工减免金额汇总(整单维度)。 【示例】NULL(用于针对“助教项目”的人工减免金额汇总(整单维度))。 【JSON字段】assistantManualDiscount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '【说明】本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。 【示例】NULL(用于本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额))。 【JSON字段】balanceAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '【说明】本单结算操作员名称(带角色前缀文字)。 【示例】NULL(用于本单结算操作员名称(带角色前缀文字))。 【JSON字段】cashierName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '【说明】本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。 【示例】NULL(用于本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠))。 【JSON字段】consumeMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '【说明】本单由优惠券抵扣的金额汇总。 【示例】NULL(用于本单由优惠券抵扣的金额汇总)。 【JSON字段】couponAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '【说明】配送地址(若存在外送业务时使用)。 【示例】NULL(用于配送地址(若存在外送业务时使用))。 【JSON字段】deliveryAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '【说明】配送费金额(如果支持外送业务)。 【示例】NULL(用于配送费金额(如果支持外送业务))。 【JSON字段】deliveryFee。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '【说明】商品小计金额(通常 = 单价 × 数量,未考虑其他折扣)。 【示例】NULL(用于商品小计金额(通常 = 单价 × 数量,未考虑其他折扣))。 【JSON字段】ledgerAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '【说明】会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。 【示例】NULL(用于会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用)。 【JSON字段】memberDeductAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '【说明】由“会员权益/折扣”产生的优惠金额总计(整单维度)。 【示例】NULL(用于由“会员权益/折扣”产生的优惠金额总计(整单维度))。 【JSON字段】memberOfferAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '【说明】本单通过线上支付渠道退回的金额(如微信/支付宝退款)。 【示例】NULL(用于本单通过线上支付渠道退回的金额(如微信/支付宝退款))。 【JSON字段】onlineReturnAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '【说明】订单备注,由收银员录入,用于记录与本单相关的特殊说明。 【示例】NULL(订单备注,由收银员录入,用于记录与本单相关的特殊说明)。 【JSON字段】orderRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '【说明】结算单编号(与 ID 独立的一套编号体系,如流水号)。 【示例】NULL(用于结算单编号(与 ID 独立的一套编号体系,如流水号))。 【JSON字段】orderSettleNumber。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '【说明】使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。 【示例】NULL(使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用)。 【JSON字段】payMemberBalance。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '【说明】本单最终支付成功时间。 【示例】NULL(用于本单最终支付成功时间)。 【JSON字段】payTime。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '【说明】结算主支付方式编码(汇总视角)。 【示例】NULL(用于结算主支付方式编码(汇总视角))。 【JSON字段】paymentMethod。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '【说明】积分抵扣对应的成本金额(成本侧)。 【示例】NULL(用于积分抵扣对应的成本金额(成本侧))。 【JSON字段】pointDiscountCost。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '【说明】积分抵扣对应的金额(售价侧)。 【示例】NULL(用于积分抵扣对应的金额(售价侧))。 【JSON字段】pointDiscountPrice。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '【说明】预付金/定金在本单中使用的金额。 【示例】NULL(用于预付金/定金在本单中使用的金额)。 【JSON字段】prepayMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '【说明】本单涉及的退款金额(汇总)。 【示例】NULL(用于本单涉及的退款金额(汇总))。 【JSON字段】refundAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '【说明】本单涉及的退货金额汇总。 【示例】NULL(用于本单涉及的退货金额汇总)。 【JSON字段】returnGoodsAmount。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '【说明】用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。 【示例】NULL(用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示)。 【JSON字段】rewardName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '【说明】结算类型字符串标识。 【示例】NULL(用于结算类型字符串标识)。 【JSON字段】settleType。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '【说明】门店地址(详细地址)。 【示例】NULL(用于门店地址(详细地址))。 【JSON字段】siteAddress。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '【说明】门店电话。 【示例】NULL(用于门店电话)。 【JSON字段】siteBusinessTel。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '【说明】门店 ID。 【示例】NULL(用于门店 ID)。 【JSON字段】siteId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '【说明】门店名称,如“朗朗桌球”。 【示例】NULL(用于门店名称,如“朗朗桌球”)。 【JSON字段】siteName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '【说明】租户 / 商户 ID(品牌维度)。 【示例】NULL(用于租户 / 商户 ID(品牌维度))。 【JSON字段】tenantId。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '【说明】租户名称,如“朗朗桌球”。 【示例】NULL(用于租户名称,如“朗朗桌球”)。 【JSON字段】tenantName。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '【说明】自定义小票内容,如商家自定义宣传语、条款等。 【示例】NULL(用于自定义小票内容,如商家自定义宣传语、条款等)。 【JSON字段】ticketCustomContent。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '【说明】小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。 【示例】NULL(小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示))。 【JSON字段】ticketRemark。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '【说明】代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。 【示例】NULL(代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录))。 【JSON字段】voucherMoney。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '【说明】不是会员卡主键,而是本次结账时的会员信息快照。 【示例】NULL(用于不是会员卡主键,而是本次结账时的会员信息快照)。 【JSON字段】memberProfile。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '【说明】本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。 【示例】NULL(用于本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构)。 【JSON字段】orderItem。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】tenantMemberCardLogs。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】settlement_ticket_details.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/settlement_ticket_details.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ batch_stock_quantity NUMERIC(18,2),
+ days_available INT,
+ provisional_total_cost NUMERIC(18,2),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ sort INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS 'ODS 原始明细表:门店商品主数据。来源:export/test-json-doc/store_goods_master.json;分析:store_goods_master-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '【说明】门店商品 ID,门店维度的商品主键。 【示例】2793025851560005(用于门店商品 ID,门店维度的商品主键)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '【说明】门店 ID。 【示例】2790685415443269(用于门店 ID)。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '【说明】门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。 【示例】朗朗桌球(用于门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案)。 【JSON字段】siteName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '【说明】租户/品牌维度的商品 ID,相当于“全局商品 ID”。 【示例】2792178593255301(用于租户/品牌维度的商品 ID,相当于“全局商品 ID”)。 【JSON字段】tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '【说明】商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。 【示例】合味道泡面(用于商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等)。 【JSON字段】goods_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '【说明】商品条形码(如 EAN-13 编码),用于扫码销售。 【示例】NULL(商品条形码(如 EAN-13 编码),用于扫码销售)。 【JSON字段】goods_bar_code。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '【说明】商品一级分类 ID。 【示例】2791941988405125(用于商品一级分类 ID)。 【JSON字段】goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '【说明】商品二级分类 ID。 【示例】2793236829620037(用于商品二级分类 ID)。 【JSON字段】goods_second_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '【说明】一级分类名称,如“零食”“酒水”“服务费”等。 【示例】零食(用于一级分类名称,如“零食”“酒水”“服务费”等)。 【JSON字段】oneCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '【说明】二级分类名称,如“面”“洋酒”“纸巾”等。 【示例】面(用于二级分类名称,如“面”“洋酒”“纸巾”等)。 【JSON字段】twoCategoryName。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '【说明】商品计量单位(销售单位)。 【示例】桶(用于商品计量单位(销售单位))。 【JSON字段】unit。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '【说明】商品标准销售价(挂牌价),单位为元。 【示例】12.0(用于商品标准销售价(挂牌价),单位为元)。 【JSON字段】sale_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '【说明】商品成本价(单件成本)。 【示例】0.0(用于商品成本价(单件成本))。 【JSON字段】cost_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '【说明】1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。 【示例】1(用于1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算)。 【JSON字段】cost_price_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '【说明】最低允许成交价(限价)。 【示例】7.0(用于最低允许成交价(限价))。 【JSON字段】min_discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '【说明】安全库存量(阈值),低于该值时系统可以提示补货。 【示例】0(用于安全库存量(阈值),低于该值时系统可以提示补货)。 【JSON字段】safe_stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '【说明】当前可用库存数量(以 unit 为单位)。 【示例】18(用于当前可用库存数量(以 unit 为单位))。 【JSON字段】stock。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '【说明】副单位库存数量。 【示例】0(用于副单位库存数量)。 【JSON字段】stock_A。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '【说明】在当前统计口径下的销售数量(总销量,单位同 unit)。 【示例】104(用于在当前统计口径下的销售数量(总销量,单位同 unit))。 【JSON字段】sale_num。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '【说明】总采购成本,单位为元。 【示例】0.0(用于总采购成本,单位为元)。 【JSON字段】total_purchase_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '【说明】累计销售数量。 【示例】104(用于累计销售数量)。 【JSON字段】total_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '【说明】平均月销量(件/月),根据某个统计周期内的销售数据折算而来。 【示例】1.32(用于平均月销量(件/月),根据某个统计周期内的销售数据折算而来)。 【JSON字段】average_monthly_sales。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.batch_stock_quantity IS '【说明】当前“批次”的库存数量(主单位)。 【示例】43(用于当前“批次”的库存数量(主单位))。 【JSON字段】batch_stock_quantity。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.days_available IS '【说明】商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间。 【示例】13(用于商品“在架天数”或“可售天数”,大致等于当前时间减去首次上架时间)。 【JSON字段】days_available。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.provisional_total_cost IS '【说明】暂估总成本,单位为元。 【示例】0.0(用于暂估总成本,单位为元)。 【JSON字段】provisional_total_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '【说明】控制商品档案是否参与任何业务(库存、销售等)。 【示例】1(用于控制商品档案是否参与任何业务(库存、销售等))。 【JSON字段】enable_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '【说明】观察值:全部为 2。 【示例】2(用于观察值:全部为 2)。 【JSON字段】audit_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】1(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】goods_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '【说明】是否纳入库存管理。 【示例】1(用于是否纳入库存管理)。 【JSON字段】is_warehousing。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '【说明】是否允许参与折扣。 【示例】1(用于是否允许参与折扣)。 【JSON字段】able_discount。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '【说明】表示是否允许跨门店调拨或跨站点共享库存。 【示例】2(用于表示是否允许跨门店调拨或跨站点共享库存)。 【JSON字段】able_site_transfer。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】forbid_sell_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '【说明】观察值:全部为 1。 【示例】1(用于观察值:全部为 1)。 【JSON字段】send_state。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '【说明】自定义标签类型。 【示例】2(用于自定义标签类型)。 【JSON字段】custom_label_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '【说明】是否需要在销售时选择规格/选项。 【示例】1(用于是否需要在销售时选择规格/选项)。 【JSON字段】option_required。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '【说明】销售渠道类型。 【示例】1(用于销售渠道类型)。 【JSON字段】sale_channel。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sort IS '【说明】排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前)。 【示例】100(排序权重,用于前端商品列表展示时的排版顺序,数值越小/越大哪个优先,具体规则看系统设定(一般是数值越小排序越靠前))。 【JSON字段】sort。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '【说明】商品备注(可以写口味说明、供应商、注意事项等)。 【示例】NULL(用于商品备注(可以写口味说明、供应商、注意事项等))。 【JSON字段】remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '【说明】商品名称的拼音首字母缩写,有时多个别名用逗号分隔。 【示例】HWDPM,GWDPM(用于商品名称的拼音首字母缩写,有时多个别名用逗号分隔)。 【JSON字段】pinyin_initial。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '【说明】商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。 【示例】https://oss.ficoo.vip/admin/8M1WM7_1753204221337.jpg(商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片)。 【JSON字段】goods_cover。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '【说明】门店商品档案创建时间(商品在门店建立档案的时间点)。 【示例】2025-07-16 11:52:51(用于门店商品档案创建时间(商品在门店建立档案的时间点))。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '【说明】最后一次修改该商品档案的时间(包括价格调整、状态变更等)。 【示例】2025-11-09 07:23:47(用于最后一次修改该商品档案的时间(包括价格调整、状态变更等))。 【JSON字段】update_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_master.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_master.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ ordergoodsid BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ returns_number INT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS 'ODS 原始明细表:门店商品销售流水。来源:export/test-json-doc/store_goods_sales_records.json;分析:store_goods_sales_records-Analysis.md。字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '【说明】本条「门店销售流水」记录的主键 ID。 【示例】2957924029550406(用于本条「门店销售流水」记录的主键 ID)。 【JSON字段】id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '【说明】租户/品牌 ID。 【示例】2790683160709957(用于租户/品牌 ID)。 【JSON字段】tenant_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '【说明】门店 ID(系统主键)。 【示例】2790685415443269(用于门店 ID(系统主键))。 【JSON字段】site_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.siteid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】siteid。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sitename IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】sitename。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '【说明】门店商品 ID。 【示例】2793026176012357(用于门店商品 ID)。 【JSON字段】site_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '【说明】租户(品牌)级商品 ID(全局商品 ID)。 【示例】2792115932417925(用于租户(品牌)级商品 ID(全局商品 ID))。 【JSON字段】tenant_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '【说明】订单结算 ID(结账单主键)。 【示例】2957922914357125(用于订单结算 ID(结账单主键))。 【JSON字段】order_settle_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '【说明】订单交易号(业务单号)。 【示例】2957858167230149(用于订单交易号(业务单号))。 【JSON字段】order_trade_no。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '【说明】订单商品明细 ID(订单内部的商品行主键)。 【示例】2957858456391557(用于订单商品明细 ID(订单内部的商品行主键))。 【JSON字段】order_goods_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ordergoodsid IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。 【示例】NULL(来自 JSON 导出的原始字段,用于保留业务取值)。 【JSON字段】ordergoodsid。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '【说明】关联支付记录的 ID。 【示例】0(用于关联支付记录的 ID)。 【JSON字段】order_pay_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '【说明】订单级优惠券 ID。 【示例】0(用于订单级优惠券 ID)。 【JSON字段】order_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '【说明】销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。 【示例】哇哈哈矿泉水(用于销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等)。 【JSON字段】ledger_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '【说明】销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。 【示例】酒水(用于销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签)。 【JSON字段】ledger_group_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '【说明】原始应收金额,公式上接近 ledger_unit_price × ledger_count。 【示例】5.0(用于原始应收金额,公式上接近 ledger_unit_price × ledger_count)。 【JSON字段】ledger_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '【说明】销售数量(以 unit 为单位,unit 字段在门店商品档案中)。 【示例】1(用于销售数量(以 unit 为单位,unit 字段在门店商品档案中))。 【JSON字段】ledger_count。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '【说明】商品在该次销售中的「结算单价」(元/单位)。 【示例】5.0(用于商品在该次销售中的「结算单价」(元/单位))。 【JSON字段】ledger_unit_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '【说明】销售流水状态。 【示例】1(用于销售流水状态)。 【JSON字段】ledger_status。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '【说明】本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。 【示例】0.0(用于本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额)。 【JSON字段】discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_price IS '【说明】折后单价(元/单位)。 【示例】5.0(用于折后单价(元/单位))。 【JSON字段】discount_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '【说明】被优惠券 / 团购券直接抵扣到这条商品明细上的金额。 【示例】0.0(用于被优惠券 / 团购券直接抵扣到这条商品明细上的金额)。 【JSON字段】coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '【说明】由会员身份(会员折扣)针对这一行商品产生的优惠金额。 【示例】0.0(用于由会员身份(会员折扣)针对这一行商品产生的优惠金额)。 【JSON字段】member_discount_amount。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '【说明】由优惠券抵扣“选项价格”的金额。 【示例】0.0(用于由优惠券抵扣“选项价格”的金额)。 【JSON字段】option_coupon_deduct_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '【说明】由会员折扣作用在“选项价格”上的优惠金额。 【示例】0.0(用于由会员折扣作用在“选项价格”上的优惠金额)。 【JSON字段】option_member_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '【说明】由积分抵扣的金额(顾客兑换积分抵现金额)。 【示例】0.0(用于由积分抵扣的金额(顾客兑换积分抵现金额))。 【JSON字段】point_discount_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '【说明】积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。 【示例】0.0(用于积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用)。 【JSON字段】point_discount_money_cost。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '【说明】商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。 【示例】5.0(用于商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额))。 【JSON字段】real_goods_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '【说明】本条销售对应的成本金额(以元计)。 【示例】0.01(用于本条销售对应的成本金额(以元计))。 【JSON字段】cost_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '【说明】本条销售对应的提成金额(给营业员/促销员的提成)。 【示例】0.0(用于本条销售对应的提成金额(给营业员/促销员的提成))。 【JSON字段】push_money。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '【说明】销售类型。 【示例】1(用于销售类型)。 【JSON字段】sales_type。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '【说明】是否单独订单标识。 【示例】1(用于是否单独订单标识)。 【JSON字段】is_single_order。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '【说明】逻辑删除标志。 【示例】0(用于逻辑删除标志)。 【JSON字段】is_delete。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '【说明】商品备注/口味说明/特殊说明。 【示例】哇哈哈矿泉水(用于商品备注/口味说明/特殊说明)。 【JSON字段】goods_remark。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '【说明】商品选项(规格/加料)的附加价格。 【示例】0.0(用于商品选项(规格/加料)的附加价格)。 【JSON字段】option_price。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '【说明】商品选项名称(如规格、口味:大杯/小杯,不加冰等)。 【示例】NULL(用于商品选项名称(如规格、口味:大杯/小杯,不加冰等))。 【JSON字段】option_value_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '【说明】名称字段,用于展示与辅助识别。 【示例】NULL(名称字段,用于展示与辅助识别)。 【JSON字段】option_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '【说明】会员券 ID(比如会员专享优惠券)。 【示例】0(用于会员券 ID(比如会员专享优惠券))。 【JSON字段】member_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '【说明】套餐券 ID。 【示例】0(用于套餐券 ID)。 【JSON字段】package_coupon_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '【说明】营业员所属组织/部门 ID。 【示例】0(用于营业员所属组织/部门 ID)。 【JSON字段】sales_man_org_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '【说明】营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。 【示例】NULL(用于营业员姓名(如果有为具体销售员记业绩,则在此填姓名))。 【JSON字段】salesman_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '【说明】营业员的系统角色 ID(例如某个角色代码表示“销售员”)。 【示例】0(用于营业员的系统角色 ID(例如某个角色代码表示“销售员”))。 【JSON字段】salesman_role_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '【说明】营业员用户 ID(系统账号 ID)。 【示例】0(用于营业员用户 ID(系统账号 ID))。 【JSON字段】salesman_user_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '【说明】操作员 ID(录入这笔销售的员工)。 【示例】2790687322443013(用于操作员 ID(录入这笔销售的员工))。 【JSON字段】operator_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '【说明】操作员姓名,文字冗余。 【示例】收银员:郑丽珊(用于操作员姓名,文字冗余)。 【JSON字段】operator_name。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '【说明】来自 JSON 导出的原始字段,用于保留业务取值。。 【示例】2(来自 JSON 导出的原始字段,用于保留业务取值。)。 【JSON字段】openSalesman。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.returns_number IS '【说明】退货数量(如果这条明细做了退货,会记录退货数量)。 【示例】0(用于退货数量(如果这条明细做了退货,会记录退货数量))。 【JSON字段】returns_number。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '【说明】球台 ID。 【示例】2793003705192517(用于球台 ID)。 【JSON字段】site_table_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '【说明】租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。 【示例】2790683528317768(用于租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度))。 【JSON字段】tenant_goods_business_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '【说明】租户级商品一级分类 ID。 【示例】2790683528350540(用于租户级商品一级分类 ID)。 【JSON字段】tenant_goods_category_id。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '【说明】销售记录创建时间,通常就是结账时间或录入时间。 【示例】2025-11-09 23:35:57(用于销售记录创建时间,通常就是结账时间或录入时间)。 【JSON字段】create_time。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '【说明】完整原始 JSON 记录快照,用于回溯与二次解析。 【示例】{...}(完整原始 JSON 记录快照,用于回溯与二次解析)。 【JSON字段】$(整条记录)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '【说明】ETL 元数据:原始导出文件名,用于数据追溯。 【示例】store_goods_sales_records.json(ETL 元数据:原始导出文件名,用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '【说明】ETL 元数据:采集来源(接口/文件路径),用于数据追溯。 【示例】export/test-json-doc/store_goods_sales_records.json(ETL 元数据:采集来源(接口/文件路径),用于数据追溯)。 【JSON字段】无(ETL元数据)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '【说明】ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。 【示例】2025-11-10T00:00:00+08:00(ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理)。 【JSON字段】无(ETL元数据)。';
+
+
diff --git a/tmp/etl_billiards_misc/tmp & Delete/schema_dwd_doc.sql.bak b/tmp/etl_billiards_misc/tmp & Delete/schema_dwd_doc.sql.bak
new file mode 100644
index 0000000..b4d2d3d
--- /dev/null
+++ b/tmp/etl_billiards_misc/tmp & Delete/schema_dwd_doc.sql.bak
@@ -0,0 +1,1878 @@
+-- Generated from DWD?????.docx; includes column comments from??
+CREATE SCHEMA IF NOT EXISTS billiards_dwd;
+SET search_path TO billiards_dwd;
+
+-- SCD2 字段统一默认值、中文注释、唯一性(业务键 + 时间段不重叠)控制
+CREATE EXTENSION IF NOT EXISTS btree_gist;
+
+DO $$
+DECLARE
+ rec RECORD;
+BEGIN
+ -- 统一 SCD2 默认值与注释,避免后续手工遗漏
+ FOR rec IN
+ SELECT table_name
+ FROM information_schema.columns
+ WHERE table_schema = 'billiards_dwd'
+ AND column_name = 'scd2_start_time'
+ LOOP
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_start_time SET DEFAULT now()', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_end_time SET DEFAULT ''9999-12-31''', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_is_current SET DEFAULT 1', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_version SET DEFAULT 1', rec.table_name);
+
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_start_time IS ''SCD2 开始时间(版本生效起点)''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_end_time IS ''SCD2 结束时间(默认 9999-12-31,表示当前版本仍有效)''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_is_current IS ''SCD2 当前版本标记:1=当前版本,0=历史版本''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_version IS ''SCD2 版本号,自增,配合时间段避免重叠''', rec.table_name);
+ END LOOP;
+
+ -- 约束:同一业务键时间段不重叠,且仅有一条当前版本
+ FOR rec IN (
+ SELECT tc.table_name,
+ string_agg(format('%I WITH =', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_eq_expr,
+ string_agg(format('%I', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_cols
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.table_schema = kcu.table_schema
+ AND tc.table_name = kcu.table_name
+ AND tc.constraint_name = kcu.constraint_name
+ WHERE tc.table_schema = 'billiards_dwd'
+ AND tc.constraint_type = 'PRIMARY KEY'
+ AND EXISTS (
+ SELECT 1 FROM information_schema.columns c
+ WHERE c.table_schema = 'billiards_dwd'
+ AND c.table_name = tc.table_name
+ AND c.column_name = 'scd2_start_time'
+ )
+ GROUP BY tc.table_name
+ )
+ LOOP
+ IF NOT EXISTS (
+ SELECT 1 FROM pg_constraint
+ WHERE conname = format('%s_scd2_no_overlap', rec.table_name)
+ AND conrelid = format('billiards_dwd.%s', rec.table_name)::regclass
+ ) THEN
+ EXECUTE format(
+ 'ALTER TABLE billiards_dwd.%I ADD CONSTRAINT %I EXCLUDE USING gist (%s, tstzrange(scd2_start_time, scd2_end_time) WITH &&) WHERE (scd2_is_current = 1);',
+ rec.table_name,
+ rec.table_name || '_scd2_no_overlap',
+ rec.pk_eq_expr
+ );
+ END IF;
+
+ IF to_regclass(format('billiards_dwd.%s_scd2_current_unique_idx', rec.table_name)) IS NULL THEN
+ EXECUTE format(
+ 'CREATE UNIQUE INDEX %I ON billiards_dwd.%I (%s) WHERE (scd2_is_current = 1);',
+ rec.table_name || '_scd2_current_unique_idx',
+ rec.table_name,
+ rec.pk_cols
+ );
+ END IF;
+ END LOOP;
+END
+$$;
+
+-- SCD2 统一约定(DIM 表使用):
+-- SCD2_start_time TIMESTAMPTZ DEFAULT now() -- 版本开始时间
+-- SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31' -- 版本结束时间
+-- SCD2_is_current INT DEFAULT 1 -- 当前版本标记(1当前/0历史)
+-- SCD2_version INT DEFAULT 1 -- 版本号,自增
+
+-- dim_site
+CREATE TABLE IF NOT EXISTS dim_site (
+ site_id BIGINT,
+ org_id BIGINT,
+ tenant_id BIGINT,
+ shop_name TEXT,
+ site_label TEXT,
+ full_address TEXT,
+ address TEXT,
+ longitude NUMERIC(10,6),
+ latitude NUMERIC(10,6),
+ tenant_site_region_id BIGINT,
+ business_tel TEXT,
+ site_type INTEGER,
+ shop_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site.site_id IS '???? ID?????????????????? site_id ??? | ??: siteProfile.id | ??: ??';
+COMMENT ON COLUMN dim_site.org_id IS '???? ID?????????? | ??: siteProfile.org_id | ??: ??';
+COMMENT ON COLUMN dim_site.tenant_id IS '?? ID????? tenant_id ??? | ??: siteProfile.tenant_id | ??: ??';
+COMMENT ON COLUMN dim_site.shop_name IS '????????? | ??: siteProfile.shop_name';
+COMMENT ON COLUMN dim_site.site_label IS '???????????????? | ??: siteProfile.site_label';
+COMMENT ON COLUMN dim_site.full_address IS '??????? | ??: siteProfile.full_address';
+COMMENT ON COLUMN dim_site.address IS '???????????? | ??: siteProfile.address';
+COMMENT ON COLUMN dim_site.longitude IS '???????? | ??: siteProfile.longitude';
+COMMENT ON COLUMN dim_site.latitude IS '???????? | ??: siteProfile.latitude';
+COMMENT ON COLUMN dim_site.tenant_site_region_id IS '????/?????????? | ??: siteProfile.tenant_site_region_id';
+COMMENT ON COLUMN dim_site.business_tel IS '????? | ??: siteProfile.business_tel';
+COMMENT ON COLUMN dim_site.site_type IS '??????????????????? | ??: siteProfile.site_type';
+COMMENT ON COLUMN dim_site.shop_status IS '??????????????????? | ??: siteProfile.shop_status';
+
+-- dim_site_Ex
+CREATE TABLE IF NOT EXISTS dim_site_Ex (
+ site_id BIGINT,
+ avatar TEXT,
+ address TEXT,
+ longitude NUMERIC(9,6),
+ latitude NUMERIC(9,6),
+ tenant_site_region_id BIGINT,
+ auto_light INTEGER,
+ light_status INTEGER,
+ light_type INTEGER,
+ light_token TEXT,
+ site_type INTEGER,
+ site_label TEXT,
+ attendance_enabled INTEGER,
+ attendance_distance INTEGER,
+ customer_service_qrcode TEXT,
+ customer_service_wechat TEXT,
+ fixed_pay_qrCode TEXT,
+ prod_env TEXT,
+ shop_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site_Ex.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
+COMMENT ON COLUMN dim_site_Ex.avatar IS '门店头像 URL。 | 来源: siteProfile.avatar';
+COMMENT ON COLUMN dim_site_Ex.address IS '地址简写。 | 来源: siteProfile.address';
+COMMENT ON COLUMN dim_site_Ex.longitude IS '经度。 | 来源: siteProfile.longitude';
+COMMENT ON COLUMN dim_site_Ex.latitude IS '纬度。 | 来源: siteProfile.latitude';
+COMMENT ON COLUMN dim_site_Ex.tenant_site_region_id IS '地区编码。 | 来源: siteProfile.tenant_site_region_id';
+COMMENT ON COLUMN dim_site_Ex.auto_light IS '是否自动控制灯光:1=是,2=否(根据系统约定)。 | 来源: siteProfile.auto_light';
+COMMENT ON COLUMN dim_site_Ex.light_status IS '灯光状态,系统预留字段。 | 来源: siteProfile.light_status';
+COMMENT ON COLUMN dim_site_Ex.light_type IS '灯光类型,预留字段。 | 来源: siteProfile.light_type';
+COMMENT ON COLUMN dim_site_Ex.light_token IS '灯光控制令牌。 | 来源: siteProfile.light_token';
+COMMENT ON COLUMN dim_site_Ex.site_type IS '门店类型枚举(未在导出中说明,视系统配置)。 | 来源: siteProfile.site_type';
+COMMENT ON COLUMN dim_site_Ex.site_label IS '门店标签,展示用。 | 来源: siteProfile.site_label';
+COMMENT ON COLUMN dim_site_Ex.attendance_enabled IS '门店是否启用考勤功能:1=启用,2=不启用。 | 来源: siteProfile.attendance_enabled';
+COMMENT ON COLUMN dim_site_Ex.attendance_distance IS '考勤打卡距离限制(米)。 | 来源: siteProfile.attendance_distance';
+COMMENT ON COLUMN dim_site_Ex.customer_service_qrcode IS '客服二维码 URL。 | 来源: siteProfile.customer_service_qrcode';
+COMMENT ON COLUMN dim_site_Ex.customer_service_wechat IS '客服微信号。 | 来源: siteProfile.customer_service_wechat';
+COMMENT ON COLUMN dim_site_Ex.fixed_pay_qrCode IS '固定收款二维码。 | 来源: siteProfile.fixed_pay_qrCode';
+COMMENT ON COLUMN dim_site_Ex.prod_env IS '环境标记(生产/测试)。 | 来源: siteProfile.prod_env';
+COMMENT ON COLUMN dim_site_Ex.shop_status IS '门店状态,未在文档解释。 | 来源: siteProfile.shop_status';
+COMMENT ON COLUMN dim_site_Ex.create_time IS '门店创建时间。 | 来源: siteProfile.create_time';
+COMMENT ON COLUMN dim_site_Ex.update_time IS '门店最近更新时间。 | 来源: siteProfile.update_time';
+
+-- dim_table
+CREATE TABLE IF NOT EXISTS dim_table (
+ table_id BIGINT,
+ site_id BIGINT,
+ table_name TEXT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ table_price NUMERIC(18,2),
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table.site_id IS '门店 ID。 | 来源: siteId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_name IS '台桌名称/编号,如 A17、888。 | 来源: tableName';
+COMMENT ON COLUMN dim_table.site_table_area_id IS '门店区 ID,用于区分 A区/B区/补时区等。 | 来源: siteTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.site_table_area_name IS '区域名称,如 “A区”“补时长”。 | 来源: siteTableAreaName';
+COMMENT ON COLUMN dim_table.tenant_table_area_id IS '租户级区域 ID。 | 来源: tenantTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_price IS '台桌基础单价,从table_fee_transactions取值。方法:对应本表id,table_fee_transactions表的site_table_id。';
+
+-- dim_table_Ex
+CREATE TABLE IF NOT EXISTS dim_table_Ex (
+ table_id BIGINT,
+ show_status INTEGER,
+ is_online_reservation INTEGER,
+ table_cloth_use_time INTEGER,
+ table_cloth_use_cycle INTEGER,
+ table_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table_Ex.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table_Ex.show_status IS '显示状态:1=正常台;其他值=特殊用途(包厢、补时长等)。 | 来源: showStatus';
+COMMENT ON COLUMN dim_table_Ex.is_online_reservation IS '是否可线上预约:1=是,2=否。 | 来源: isOnlineReservation';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_time IS '已使用台呢时长(秒)。 | 来源: tableClothUseTime';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_cycle IS '台呢更换周期阈值(秒)。 | 来源: tableClothUseCycle';
+COMMENT ON COLUMN dim_table_Ex.table_status IS '当前台桌状态:1=空闲,2=使用中,3=暂停中,4=锁定。 | 来源: tableStatus';
+
+-- dim_assistant
+CREATE TABLE IF NOT EXISTS dim_assistant (
+ assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_no TEXT,
+ real_name TEXT,
+ nickname TEXT,
+ mobile TEXT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ team_id BIGINT,
+ team_name TEXT,
+ level INTEGER,
+ entry_time TIMESTAMPTZ,
+ resign_time TIMESTAMPTZ,
+ leave_status INTEGER,
+ assistant_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant.user_id IS '系统用户 ID,用于统一跨模块身份。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.assistant_no IS '助教工号/编号,业务识别用。 | 来源: assistant_no';
+COMMENT ON COLUMN dim_assistant.real_name IS '助教真实姓名。 | 来源: real_name';
+COMMENT ON COLUMN dim_assistant.nickname IS '前台展示昵称。 | 来源: nickname';
+COMMENT ON COLUMN dim_assistant.mobile IS '手机号码。 | 来源: mobile';
+COMMENT ON COLUMN dim_assistant.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.site_id IS '门店 ID。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_id IS '助教团队 ID。 | 来源: team_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_name IS '团队名称。 | 来源: team_name';
+COMMENT ON COLUMN dim_assistant.level IS '助教等级:8=管理员、10=初级、20=中级、30=高级、40=专家。 | 来源: level';
+COMMENT ON COLUMN dim_assistant.entry_time IS '入职时间。 | 来源: entry_time';
+COMMENT ON COLUMN dim_assistant.resign_time IS '离职时间;远未来日期表示在职。 | 来源: resign_time';
+COMMENT ON COLUMN dim_assistant.leave_status IS '在职状态:0=在职,1=已离职。 | 来源: leave_status';
+COMMENT ON COLUMN dim_assistant.assistant_status IS '账号启用状态:1=启用,2=停用/冻结。 | 来源: assistant_status';
+
+-- dim_assistant_Ex
+CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
+ assistant_id BIGINT,
+ gender INTEGER,
+ birth_date TIMESTAMPTZ,
+ avatar TEXT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ height NUMERIC(5,2),
+ weight NUMERIC(5,2),
+ shop_name TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ person_org_id BIGINT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ assistant_grade DOUBLE PRECISION,
+ sum_grade DOUBLE PRECISION,
+ get_grade_times INTEGER,
+ charge_way INTEGER,
+ allow_cx INTEGER,
+ is_guaranteed INTEGER,
+ salary_grant_enabled INTEGER,
+ entry_type INTEGER,
+ entry_sign_status INTEGER,
+ resign_sign_status INTEGER,
+ work_status INTEGER,
+ show_status INTEGER,
+ show_sort INTEGER,
+ online_status INTEGER,
+ is_delete INTEGER,
+ criticism_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ last_update_name TEXT,
+ order_trade_no BIGINT,
+ ding_talk_synced INTEGER,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ light_status INTEGER,
+ is_team_leader INTEGER,
+ serial_number BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant_Ex.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant_Ex.gender IS '性别枚举:0=未填/保密,1=男,2=女。 | 来源: gender';
+COMMENT ON COLUMN dim_assistant_Ex.birth_date IS '出生日期,默认为 0001-01-01 表示未设置。 | 来源: birth_date';
+COMMENT ON COLUMN dim_assistant_Ex.avatar IS '头像 URL。 | 来源: avatar';
+COMMENT ON COLUMN dim_assistant_Ex.introduce IS '个人简介文案(目前为空)。 | 来源: introduce';
+COMMENT ON COLUMN dim_assistant_Ex.video_introduction_url IS '视频介绍 URL。 | 来源: video_introduction_url';
+COMMENT ON COLUMN dim_assistant_Ex.height IS '身高(厘米),0 表示未填。 | 来源: height';
+COMMENT ON COLUMN dim_assistant_Ex.weight IS '体重(公斤),0 表示未填。 | 来源: weight';
+COMMENT ON COLUMN dim_assistant_Ex.shop_name IS '门店名称。 | 来源: shop_name';
+COMMENT ON COLUMN dim_assistant_Ex.group_id IS '上级分组 ID,未使用。 | 来源: group_id';
+COMMENT ON COLUMN dim_assistant_Ex.group_name IS '上级分组名称,空。 | 来源: group_name';
+COMMENT ON COLUMN dim_assistant_Ex.person_org_id IS '人事组织 ID,用于权限和报表分组。 | 来源: person_org_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_id IS '预留员工 ID(全部为0)。 | 来源: staff_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_profile_id IS '外部人事档案 ID(全部为0)。 | 来源: staff_profile_id';
+COMMENT ON COLUMN dim_assistant_Ex.assistant_grade IS '平均评分(0 表示暂无)。 | 来源: assistant_grade';
+COMMENT ON COLUMN dim_assistant_Ex.sum_grade IS '总评分累加值。 | 来源: sum_grade';
+COMMENT ON COLUMN dim_assistant_Ex.get_grade_times IS '累计评分次数。 | 来源: get_grade_times';
+COMMENT ON COLUMN dim_assistant_Ex.charge_way IS '计费方式:2=计时,其他未出现。 | 来源: charge_way';
+COMMENT ON COLUMN dim_assistant_Ex.allow_cx IS '是否允许促销计费:1=允许。 | 来源: allow_cx';
+COMMENT ON COLUMN dim_assistant_Ex.is_guaranteed IS '是否有保底:1=是。 | 来源: is_guaranteed';
+COMMENT ON COLUMN dim_assistant_Ex.salary_grant_enabled IS '薪资发放开关(值2,具体含义未知)。 | 来源: salary_grant_enabled';
+COMMENT ON COLUMN dim_assistant_Ex.entry_type IS '入职类型:1=正式;其他未出现。 | 来源: entry_type';
+COMMENT ON COLUMN dim_assistant_Ex.entry_sign_status IS '入职签约状态:0=未签约,1=已签约(未出现)。 | 来源: entry_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.resign_sign_status IS '离职签约状态,未出现非 0。 | 来源: resign_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.work_status IS '工作状态:1=在岗,2=离岗。与 leave_status 呼应。 | 来源: work_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_status IS '前台展示状态:1=显示;其他值未出现。 | 来源: show_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_sort IS '前端排序序号。 | 来源: show_sort';
+COMMENT ON COLUMN dim_assistant_Ex.online_status IS '在线状态:1=在线。 | 来源: online_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_delete IS '逻辑删除标记:0=未删除,1=已删除。 | 来源: is_delete';
+COMMENT ON COLUMN dim_assistant_Ex.criticism_status IS '投诉状态:1=正常,2=有投诉。 | 来源: criticism_status';
+COMMENT ON COLUMN dim_assistant_Ex.create_time IS '账号创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_assistant_Ex.update_time IS '账号最近修改时间。 | 来源: update_time';
+COMMENT ON COLUMN dim_assistant_Ex.start_time IS '配置生效开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_assistant_Ex.end_time IS '配置生效结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_id IS '最近服务的台桌 ID(未必存在)。 | 来源: last_table_id';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_name IS '最近服务球台名称。 | 来源: last_table_name';
+COMMENT ON COLUMN dim_assistant_Ex.last_update_name IS '最近更新该账号的管理员。 | 来源: last_update_name';
+COMMENT ON COLUMN dim_assistant_Ex.order_trade_no IS '最近关联的订单号(非外键,仅做展示)。 | 来源: order_trade_no';
+COMMENT ON COLUMN dim_assistant_Ex.ding_talk_synced IS '是否同步钉钉:1=已同步。 | 来源: ding_talk_synced';
+COMMENT ON COLUMN dim_assistant_Ex.site_light_cfg_id IS '灯控配置 ID(未启用)。 | 来源: site_light_cfg_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_equipment_id IS '灯控设备 ID(未启用)。 | 来源: light_equipment_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_status IS '灯控状态(值2,具体含义未知)。 | 来源: light_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_team_leader IS '是否团队长:0=否,1=是。 | 来源: is_team_leader';
+COMMENT ON COLUMN dim_assistant_Ex.serial_number IS '来源: serial_number';
+
+-- dim_member
+CREATE TABLE IF NOT EXISTS dim_member (
+ member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ mobile TEXT,
+ nickname TEXT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member.system_member_id IS '跨租户全局会员 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.register_site_id IS '注册门店 ID。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.mobile IS '会员手机号。 | 来源: mobile';
+COMMENT ON COLUMN dim_member.nickname IS '昵称(未必是真实姓名)。 | 来源: nickname';
+COMMENT ON COLUMN dim_member.member_card_grade_code IS '会员等级代码:1=金卡?2=银卡?3=钻石卡?4=黑卡?(按照 MD 文档枚举)。 | 来源: member_card_grade_code';
+COMMENT ON COLUMN dim_member.member_card_grade_name IS '等级名称,中文描述。 | 来源: member_card_grade_name';
+COMMENT ON COLUMN dim_member.create_time IS '会员档案创建时间。 | 来源: create_time';
+
+-- dim_member_Ex
+CREATE TABLE IF NOT EXISTS dim_member_Ex (
+ member_id BIGINT,
+ referrer_member_id BIGINT,
+ point NUMERIC(18,2),
+ register_site_name TEXT,
+ growth_value NUMERIC(18,2),
+ user_status INTEGER,
+ status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member_Ex.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_Ex.referrer_member_id IS '推荐人会员 ID,营销分析用。 | 来源: referrer_member_id';
+COMMENT ON COLUMN dim_member_Ex.point IS '积分余额(暂未启用)。 | 来源: point';
+COMMENT ON COLUMN dim_member_Ex.register_site_name IS '注册门店名称。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_Ex.growth_value IS '成长值,暂未启用。 | 来源: growth_value';
+COMMENT ON COLUMN dim_member_Ex.user_status IS '会员状态枚举:1=正常,其它值未出现。 | 来源: user_status';
+COMMENT ON COLUMN dim_member_Ex.status IS '帐户状态:1=正常;其它值未出现。 | 来源: status';
+
+-- dim_member_card_account
+CREATE TABLE IF NOT EXISTS dim_member_card_account (
+ member_card_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ card_type_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ balance NUMERIC(18,2),
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_consume_time TIMESTAMPTZ,
+ status INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account.tenant_id IS '租户/品牌 ID,用于分隔不同业务主体。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.register_site_id IS '开卡门店 ID,对应 dim_site.site_id。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.tenant_member_id IS '对应会员档案中的 member_id(本租户内)。0 表示未绑定会员。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.system_member_id IS '全局会员 ID,用于跨租户统一会员身份。0 表示未绑定会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.card_type_id IS '卡种 ID,指向卡种配置表。与下面的 grade_code 共同定义卡类别。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code IS '卡等级/卡类代码,区别不同类别卡。2790683528022853=储值卡,2790683528022856=活动抵用券,2790683528022855=台费卡,2790683528022858=酒水卡,2790683528022857=月卡';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code_name IS '卡等级中文名称,与 member_card_grade_code 一一对应。 | 来源: member_card_grade_code_name';
+COMMENT ON COLUMN dim_member_card_account.member_card_type_name IS '卡类型名称,通常与 grade_code_name 相同,纯展示字段。 | 来源: member_card_type_name';
+COMMENT ON COLUMN dim_member_card_account.member_name IS '持卡会员姓名快照,部分为空表示未绑定。 | 来源: member_name';
+COMMENT ON COLUMN dim_member_card_account.member_mobile IS '持卡会员手机号快照。 | 来源: member_mobile';
+COMMENT ON COLUMN dim_member_card_account.balance IS '当前余额或额度。对储值卡表示余额,对其他卡表示剩余金额或次数。 | 来源: balance';
+COMMENT ON COLUMN dim_member_card_account.start_time IS '卡片有效期开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_member_card_account.end_time IS '卡片有效期结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_member_card_account.last_consume_time IS '最近一次消费时间;若为 "1970-01-01" 表示未消费过。 | 来源: last_consume_time';
+COMMENT ON COLUMN dim_member_card_account.status IS '卡状态:1=正常可用;4=过期/停用。其他值在数据中未出现。 | 来源: status';
+COMMENT ON COLUMN dim_member_card_account.is_delete IS '逻辑删除标记:0=未删除;1=已删除。 | 来源: is_delete';
+
+-- dim_member_card_account_Ex
+CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
+ member_card_id BIGINT,
+ site_name TEXT,
+ tenant_name VARCHAR(64),
+ tenantAvatar TEXT,
+ effect_site_id BIGINT,
+ able_cross_site INTEGER,
+ card_physics_type INTEGER,
+ card_no TEXT,
+ bind_password TEXT,
+ use_scene TEXT,
+ denomination NUMERIC(18,2),
+ create_time TIMESTAMPTZ,
+ disable_start_time TIMESTAMPTZ,
+ disable_end_time TIMESTAMPTZ,
+ is_allow_give INTEGER,
+ is_allow_order_deduct INTEGER,
+ sort INTEGER,
+ table_discount NUMERIC(10,2),
+ goods_discount NUMERIC(10,2),
+ assistant_discount NUMERIC(10,2),
+ assistant_reward_discount NUMERIC(10,2),
+ table_service_discount NUMERIC(10,2),
+ goods_service_discount NUMERIC(10,2),
+ assistant_service_discount NUMERIC(10,2),
+ coupon_discount NUMERIC(10,2),
+ table_discount_sub_switch INTEGER,
+ goods_discount_sub_switch INTEGER,
+ assistant_discount_sub_switch INTEGER,
+ assistant_reward_discount_sub_switch INTEGER,
+ goods_discount_range_type INTEGER,
+ table_deduct_radio NUMERIC(10,2),
+ goods_deduct_radio NUMERIC(10,2),
+ assistant_deduct_radio NUMERIC(10,2),
+ table_service_deduct_radio NUMERIC(10,2),
+ goods_service_deduct_radio NUMERIC(10,2),
+ assistant_service_deduct_radio NUMERIC(10,2),
+ assistant_reward_deduct_radio NUMERIC(10,2),
+ coupon_deduct_radio NUMERIC(10,2),
+ cardSettleDeduct NUMERIC(18,2),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ tableAreaId TEXT,
+ goodsCategoryId TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account_Ex.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account_Ex.site_name IS '门店名称展示字段(全部相同)。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenant_name IS '租户名称(当前导出为空)。 | 来源: tenantName';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenantAvatar IS '租户头像 URL(当前导出为空)。 | 来源: tenantAvatar';
+COMMENT ON COLUMN dim_member_card_account_Ex.effect_site_id IS '卡片限定生效门店 ID。0 表示不限门店,配合 able_cross_site=1 表示全店通用。 | 来源: effect_site_id';
+COMMENT ON COLUMN dim_member_card_account_Ex.able_cross_site IS '是否允许跨门店使用该卡:1=允许跨店;0=仅限开卡门店。 | 来源: able_cross_site';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_physics_type IS '物理卡类型:1=实体/标准卡;其他值未出现,含义未知。 | 来源: card_physics_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_no IS '物理卡号或条码(当前全部为空)。 | 来源: card_no';
+COMMENT ON COLUMN dim_member_card_account_Ex.bind_password IS '卡绑定密码(未启用)。 | 来源: bind_password';
+COMMENT ON COLUMN dim_member_card_account_Ex.use_scene IS '使用场景说明(当前为空)。 | 来源: use_scene';
+COMMENT ON COLUMN dim_member_card_account_Ex.denomination IS '面额或初始储值额度(当前均为 0.0,未启用)。 | 来源: denomination';
+COMMENT ON COLUMN dim_member_card_account_Ex.create_time IS '卡片创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_start_time IS '卡片禁用开始时间,当前为默认值表示未禁用。 | 来源: disable_start_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_end_time IS '卡片禁用结束时间,当前为默认值表示未禁用。 | 来源: disable_end_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_give IS '是否允许转赠给他人:0=不允许;1=允许。 | 来源: is_allow_give';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_order_deduct IS '是否允许在订单层面统一扣款:0=不允许;1=允许。 | 来源: is_allow_order_deduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.sort IS '前端排序序号。 | 来源: sort';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount IS '台费折扣率(折扣百分比,10.0=不打折,9.0=九折等)。当前全部 10.0。 | 来源: table_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount IS '商品折扣率,当前为 10.0 表示无折扣。 | 来源: goods_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount IS '助教服务折扣率,当前为 10.0。 | 来源: assistant_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount IS '助教奖励折扣率,当前为 10.0(未启用)。 | 来源: assistant_reward_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_discount IS '台费服务类折扣率,当前为 10.0。 | 来源: table_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_discount IS '商品服务折扣率,当前为 10.0。 | 来源: goods_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_discount IS '助教服务类折扣率,当前为 10.0。 | 来源: assistant_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_discount IS '使用券的折扣比例(全部 10.0,未使用)。 | 来源: coupon_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount_sub_switch IS '台费折扣叠加开关:1=叠加其他折扣;2=不叠加,仅用卡折扣。 | 来源: table_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_sub_switch IS '商品折扣叠加开关,意义同上。 | 来源: goods_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount_sub_switch IS '助教折扣叠加开关,意义同上。 | 来源: assistant_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount_sub_switch IS '助教奖励折扣叠加开关(未启用)。 | 来源: assistant_reward_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_range_type IS '商品折扣范围类型,未在文档说明具体含义。 | 来源: goods_discount_range_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_deduct_radio IS '台费抵扣比例(百分比)。100.0 表示允许全额抵扣;0=不允许。 | 来源: table_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_deduct_radio IS '商品抵扣比例,意义同上。 | 来源: goods_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_deduct_radio IS '助教抵扣比例,意义同上。 | 来源: assistant_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_deduct_radio IS '台费服务金抵扣比例。 | 来源: table_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_deduct_radio IS '商品服务金抵扣比例。 | 来源: goods_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_deduct_radio IS '助教服务金抵扣比例。 | 来源: assistant_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_deduct_radio IS '助教奖励金抵扣比例(未启用)。 | 来源: assistant_reward_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_deduct_radio IS '券抵扣比例(未启用)。 | 来源: coupon_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.cardSettleDeduct IS '结算时统一扣卡金额配置(当前为 0.0,未使用)。 | 来源: cardSettleDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableCardDeduct IS '台费扣卡金额配置,当前 0.0。 | 来源: tableCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableServiceCardDeduct IS '台费服务金扣卡金额配置。 | 来源: tableServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCarDeduct IS '商品扣卡金额配置。 | 来源: goodsCarDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsServiceCardDeduct IS '商品服务金扣卡金额配置。 | 来源: goodsServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantCardDeduct IS '助教扣卡金额配置。 | 来源: assistantCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantServiceCardDeduct IS '助教服务金扣卡金额配置。 | 来源: assistantServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantRewardCardDeduct IS '助教奖励金扣卡金额配置(未启用)。 | 来源: assistantRewardCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.couponCardDeduct IS '使用券扣卡金额配置。 | 来源: couponCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.deliveryFeeDeduct IS '配送费扣卡金额配置(未启用)。 | 来源: deliveryFeeDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableAreaId IS '可用台区 ID 列表,空表示不限台区。 | 来源: tableAreaId';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCategoryId IS '可用商品分类 ID 列表,空表示不限制商品类别。 | 来源: goodsCategoryId';
+COMMENT ON COLUMN dim_member_card_account_Ex.pdAssisnatLevel IS '允许的陪打助教等级列表,空表示不限。 | 来源: pdAssisnatLevel';
+COMMENT ON COLUMN dim_member_card_account_Ex.cxAssisnatLevel IS '允许的促销助教等级列表,空表示不限。 | 来源: cxAssisnatLevel';
+
+-- dim_tenant_goods
+CREATE TABLE IF NOT EXISTS dim_tenant_goods (
+ tenant_goods_id BIGINT,
+ tenant_id BIGINT,
+ supplier_id BIGINT,
+ category_name VARCHAR(64),
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ goods_name VARCHAR(128),
+ goods_number VARCHAR(64),
+ unit VARCHAR(16),
+ market_price NUMERIC(18,2),
+ goods_state INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods.tenant_id IS '租户/品牌 ID,用于区分不同商户。当前样本中全表同一值,但模型上应作为维表外键,用于关联租户维度。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.supplier_id IS '供应商 ID,用于关联供应商档案维度。当前样本全部为 0,说明门店尚未维护供应商信息或导出视图未包含真实供应商关联,但字段含义明确。 | 来源: supplier_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.category_name IS '商品一级分类名称(可读名称),例如:零食、饮料、香烟、雪糕、小吃、酒水、面、槟榔等。真实分类关联通过 goods_category_id 与 goods_second_category_id 实现,此字段主要用于展示和直观分析。 | 来源: categoryName';
+COMMENT ON COLUMN dim_tenant_goods.goods_category_id IS '商品一级分类 ID。与分类维表(例如 dim_goods_category)关联,构成商品分类的第一层。一个 goods_category_id 对应一个 category_name。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_second_category_id IS '商品二级分类 ID。与分类维表的二级节点关联,用于更细粒度的品类统计。取值数目约十四种,每个值属于某个一级分类之下。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_name IS '商品名称(前台展示名),如 “东方树叶”“红烧牛肉面”“百威 235 毫升”等。当前样本中基本唯一。作为用户认知的主显示名称,用于报表、前台展示、小票打印。 | 来源: goods_name';
+COMMENT ON COLUMN dim_tenant_goods.goods_number IS '商品内部编号或自定义货号。当前样本中各记录不重复,如 “1”“2”“10”“11” 等。可用于与其他系统对接或人工查找,有一定对账和排错价值。 | 来源: goods_number';
+COMMENT ON COLUMN dim_tenant_goods.unit IS '商品计量单位,例如:瓶、包、个、份、根、盒、杯、桶、盘、支等。用于解释数量含义,是销售数量与库存数量的度量单位。 | 来源: unit';
+COMMENT ON COLUMN dim_tenant_goods.market_price IS '商品标价或标准销售单价。例如 2、5、6、8、10、12、15、18、20、28 元。POS 默认销售价格,结算时的基础金额字段。 | 来源: market_price';
+COMMENT ON COLUMN dim_tenant_goods.goods_state IS '商品状态枚举。当前样本全部为 1,推测含义为“正常”“已上架”或“有效”。其他值(数据中未出现)通常表示下架、停用或草稿状态。用于控制商品是否可销售。 | 来源: goods_state';
+COMMENT ON COLUMN dim_tenant_goods.create_time IS '商品档案创建时间,格式为 “YYYY-MM-DD HH:MM:SS”。每条记录唯一。用于增量抽取和审计,也可用于分析商品生命周期。 | 来源: create_time';
+COMMENT ON COLUMN dim_tenant_goods.update_time IS '商品档案最近一次修改时间,可为空(表示自创建后未修改)。用于增量同步、变化跟踪和审计分析。 | 来源: update_time';
+COMMENT ON COLUMN dim_tenant_goods.is_delete IS '逻辑删除标志。枚举:0 表示未删除(有效商品);1 表示已逻辑删除(在前台不再展示)。当前样本全部为 0。用于软删除控制和历史数据保留。 | 来源: is_delete';
+
+-- dim_tenant_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
+ tenant_goods_id BIGINT,
+ remark_name VARCHAR(128),
+ pinyin_initial VARCHAR(128),
+ goods_cover VARCHAR(512),
+ goods_bar_code VARCHAR(64),
+ commodity_code VARCHAR(64),
+ commodity_code_list VARCHAR(256),
+ min_discount_price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ cost_price_type INTEGER,
+ able_discount INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ is_in_site BOOLEAN,
+ able_site_transfer INTEGER,
+ common_sale_royalty INTEGER,
+ point_sale_royalty INTEGER,
+ out_goods_id BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods_Ex.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods_Ex.remark_name IS '商品备注名或别名,目前样本中均为空。设计用途为简写名、特殊展示名或内部备注,在当前门店尚未启用。 | 来源: remark_name';
+COMMENT ON COLUMN dim_tenant_goods_Ex.pinyin_initial IS '商品拼音首字母或助记码,用于前台按拼音检索,如 “DFSY,DFSX”“HSNRM,GSNRM”“SP” 等。主要为操作便利,对经营分析影响较小。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_cover IS '商品封面图片 URL,用于前端展示商品图片。多个商品可能共用同一图片。对经营和结算逻辑无直接影响。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_bar_code IS '商品条码(如 EAN 码)。当前样本全部为空。含义明确但尚未使用,未来可用于扫码收银或与第三方商品库对接。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code IS '对外商品编码或系列编码,用于与外部系统或其他内部模块对接。例如 “10000”“100000”“10000028”等。一个编码在多条商品上复用,说明它不是主键而是“系列标识”或“外部编码”。具体业务含义依赖上游系统定义。 | 来源: commodity_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code_list IS '商品编码列表的序列化形式,对应源 JSON 的数组字段(当前每条记录仅一个元素)。设计上支持 “一个商品多个编码” 场景,目前仅为 commodity_code 的冗余表现形式。 | 来源: commodityCode';
+COMMENT ON COLUMN dim_tenant_goods_Ex.min_discount_price IS '商品可售最低价(底价)。部分记录为 0.00,表示未设置底价或沿用系统默认规则。用于限制打折或手动改价的下限,防止亏损销售。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price IS '商品成本价,当前大多数为 0.00,仅少数录入 2.0、2.5、3.0 等。用于成本核算与毛利分析。虽当前门店未完整维护,但字段含义清晰,属于成本分析必备结构。 | 来源: cost_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price_type IS '成本价格类型枚举,用于标识成本价的来源或计算方式。已知取值:1 和 2。常见推测:1 表示手工录入成本;2 表示按最近进货价或加权平均价生成。具体含义需结合系统枚举字典确认。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_discount IS '是否允许该商品参与折扣的标志。已知取值:1。按命名推断枚举约定为:1 表示允许参与打折;0 表示不允许参与打折(当前样本未出现)。配合活动、整单折扣等控制哪些商品可享优惠。 | 来源: able_discount';
+COMMENT ON COLUMN dim_tenant_goods_Ex.sale_channel IS '销售渠道类型枚举。当前样本全部为 1,推测为“线下门店正常销售渠道”。理论上可扩展为不同渠道值,例如外卖、小程序、电商等,用于渠道维度分析。具体枚举说明依赖系统配置。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_warehousing IS '是否纳入库存管理的标志。已知取值:1,表示纳入库存管理;0 则表示不纳入库存管理(虚拟商品等,当前未出现)。本门店所有商品均启用库存管理。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_in_site IS '是否在当前门店启用或上架。当前样本全部为 false。由于该文件是租户级商品档案视图,且 isInSite 全为 false,该字段在本视图的实际含义存在不确定性,可能仅在门店级商品表中才有明确业务意义。 | 来源: isInSite';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_site_transfer IS '是否允许门店间调拨或门店级操作的枚举。已知取值:2 为绝大多数,0 为少数一条。按命名推测大致含义为:2 表示允许调拨或默认允许;0 表示禁止调拨。实际枚举定义需查阅系统配置,当前无法完全确定具体业务规则。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_tenant_goods_Ex.common_sale_royalty IS '普通销售提成或佣金配置字段,单位和含义需结合上游系统(可能为金额或比例)。当前样本全部为 0,说明未启用商品级提成配置。 | 来源: common_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.point_sale_royalty IS '积分销售相关的提成或赠送规则配置字段。当前样本全部为 0,同样未启用该功能。具体数值含义(百分比或固定值)需结合系统定义。 | 来源: point_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.out_goods_id IS '外部系统商品 ID,用于对接第三方平台或统一商品库时作为映射主键。目前样本全部为 0,说明尚未配置外部商品映射,具体对接规则依赖上游系统。 | 来源: out_goods_id';
+
+-- dim_store_goods
+CREATE TABLE IF NOT EXISTS dim_store_goods (
+ site_goods_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ category_level1_name TEXT,
+ category_level2_name TEXT,
+ batch_stock_qty INTEGER,
+ sale_qty INTEGER,
+ total_sales_qty INTEGER,
+ sale_price NUMERIC(18,2),
+ created_at TIMESTAMPTZ,
+ updated_at TIMESTAMPTZ,
+ avg_monthly_sales NUMERIC(18,4),
+ goods_state INTEGER,
+ enable_status INTEGER,
+ send_state INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods.tenant_id IS '租户/品牌 ID,同一品牌下多个门店共享,用于跨门店汇总分析。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.site_id IS '门店 ID,对应门店维度表主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.tenant_goods_id IS '租户级(品牌级)商品 ID,用于关联 dim_tenant_goods,实现跨门店统一商品档案。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_name IS '商品名称,例如“合味道泡面”“地道肠”“茶位费”。 | 来源: goods_name';
+COMMENT ON COLUMN dim_store_goods.goods_category_id IS '商品一级分类 ID,对应商品分类维表主键,与 category_level1_name 一一对应。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_second_category_id IS '商品二级分类 ID,其父分类为 goods_category_id。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.category_level1_name IS '一级分类名称,如“零食”“酒水”“服务费”,用于报表维度展示。 | 来源: oneCategoryName';
+COMMENT ON COLUMN dim_store_goods.category_level2_name IS '二级分类名称,如“面”“洋酒”“纸巾”,用于更细粒度分类分析。 | 来源: twoCategoryName';
+COMMENT ON COLUMN dim_store_goods.batch_stock_qty IS '当前成本批次的库存数量,用于按 cost_price 估算库存价值。 | 来源: batch_stock_quantity';
+COMMENT ON COLUMN dim_store_goods.sale_qty IS '截至导出时的销售数量(件),当前数据中与 total_sales_qty 相同。 | 来源: sale_num';
+COMMENT ON COLUMN dim_store_goods.total_sales_qty IS '累计销售数量;当前导出周期下与 sale_qty 一致,为历史全量口径。 | 来源: total_sales';
+COMMENT ON COLUMN dim_store_goods.sale_price IS '商品标准销售价(挂牌价),单位为元。实际结算可能有折扣或券抵扣。 | 来源: sale_price';
+COMMENT ON COLUMN dim_store_goods.created_at IS '门店商品档案创建时间(在门店建立该商品档案时的时间点)。 | 来源: create_time';
+COMMENT ON COLUMN dim_store_goods.updated_at IS '最近一次修改商品档案的时间(包括价格调整、状态变更等)。 | 来源: update_time';
+COMMENT ON COLUMN dim_store_goods.avg_monthly_sales IS '平均月销量(件/月),由某个统计周期内销售数据折算而来,用于补货和品类管理分析。 | 来源: average_monthly_sales';
+COMMENT ON COLUMN dim_store_goods.goods_state IS '商品基础状态枚举:1=正常状态(主流值),2=特殊状态(如新建未完全启用或停售但未彻底下架,通常伴随 stock=0、days_on_shelf=0)。 | 来源: goods_state';
+COMMENT ON COLUMN dim_store_goods.enable_status IS '档案启用状态:1=启用;2=停用(推测,样本中未出现);控制商品档案是否参与业务处理。 | 来源: enable_status';
+COMMENT ON COLUMN dim_store_goods.send_state IS '销售端可售状态:1=可销售/可下单;其他值可能代表停售或仅内部使用(当前样本全部为 1)。 | 来源: send_state';
+COMMENT ON COLUMN dim_store_goods.is_delete IS '逻辑删除标志:0=未删除(有效档案);1=已删除(逻辑删除,不再参与业务但保留历史引用)。 | 来源: is_delete';
+
+-- dim_store_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
+ site_goods_id BIGINT,
+ site_name TEXT,
+ unit TEXT,
+ goods_barcode TEXT,
+ goods_cover_url TEXT,
+ pinyin_initial TEXT,
+ stock_qty INTEGER,
+ stock_secondary_qty INTEGER,
+ safety_stock_qty INTEGER,
+ cost_price NUMERIC(18,4),
+ cost_price_type INTEGER,
+ provisional_total_cost NUMERIC(18,2),
+ total_purchase_cost NUMERIC(18,2),
+ min_discount_price NUMERIC(18,2),
+ is_discountable INTEGER,
+ days_on_shelf INTEGER,
+ audit_status INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ freeze_status INTEGER,
+ forbid_sell_status INTEGER,
+ able_site_transfer INTEGER,
+ custom_label_type INTEGER,
+ option_required INTEGER,
+ remark TEXT,
+ sort_order INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods_Ex.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods_Ex.site_name IS '门店名称,例如“朗朗桌球”,是对 site_id 的冗余展示,方便直接阅读。 | 来源: siteName';
+COMMENT ON COLUMN dim_store_goods_Ex.unit IS '销售计量单位,如“包”“瓶”“个”“份”“杯”等。 | 来源: unit';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_barcode IS '商品条形码,用于扫码销售;当前样本多为空。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_cover_url IS '商品图片 URL,用于前端展示商品图片。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_store_goods_Ex.pinyin_initial IS '商品名称拼音首字母缩写,有时多个别名用逗号分隔,用于按字母快速检索和排序。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_qty IS '当前主单位可用库存数量,以 unit 为单位。 | 来源: stock';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_secondary_qty IS '副单位库存数量;若商品存在双单位(如箱/瓶),用于记录副单位库存;当前门店未启用双单位库存,样本中为 0。 | 来源: stock_A';
+COMMENT ON COLUMN dim_store_goods_Ex.safety_stock_qty IS '安全库存阈值,低于该值时系统可提示补货;当前门店尚未配置,样本中为 0。 | 来源: safe_stock';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price IS '商品单件成本价,单位元;部分商品为 0,表示未录入或由其它模块结转成本。 | 来源: cost_price';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price_type IS '成本类型枚举:1=固定成本价(按 cost_price 计),2=动态成本价(按采购单等方式结转,当前多数仍为暂估)。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_store_goods_Ex.provisional_total_cost IS '当前库存暂估总成本,单位元;通常约等于 batch_stock_qty × cost_price。 | 来源: provisional_total_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.total_purchase_cost IS '当前库存总采购成本,单位元;当前样本中与 provisional_total_cost 相等,为后续精算成本预留。 | 来源: total_purchase_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.min_discount_price IS '最低允许成交价(限价),单位元;收银改价时需保证成交价 ≥ 此值,为 0 时表示未设置限价或由其它规则控制。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_store_goods_Ex.is_discountable IS '是否允许参与折扣的标志:1=允许参与折扣;0=不参与任何折扣策略。当前样本全部为 1。 | 来源: able_discount';
+COMMENT ON COLUMN dim_store_goods_Ex.days_on_shelf IS '商品在架天数或可售天数,大致等于当前时间减去首次上架时间;0 通常表示刚建档或刚启用。 | 来源: days_available';
+COMMENT ON COLUMN dim_store_goods_Ex.audit_status IS '审核状态枚举:2=审核通过(当前唯一值);其他值可能代表待提交、待审核、审核不通过等。 | 来源: audit_status';
+COMMENT ON COLUMN dim_store_goods_Ex.sale_channel IS '销售渠道枚举:当前样本全部为 1 表示线下门店渠道;其他值可用于区分外卖、线上商城等渠道。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_store_goods_Ex.is_warehousing IS '是否纳入库存管理:1=参与库存管理(有出入库流水);0 或其他值可能表示不计库存(样本中全部为 1)。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_store_goods_Ex.freeze_status IS '冻结状态:0=未冻结;非 0 可能表示锁定库存或禁止出库,具体业务规则需系统确认。 | 来源: freeze';
+COMMENT ON COLUMN dim_store_goods_Ex.forbid_sell_status IS '禁止销售状态:1=未禁止,允许销售;2=被禁止销售,即使上架也不能卖(含义基于命名和行业惯例推测)。 | 来源: forbid_sell_status';
+COMMENT ON COLUMN dim_store_goods_Ex.able_site_transfer IS '是否允许跨门店调拨或跨站点共享库存:2=不允许跨店调拨(当前主流值);0=未配置(个别记录),含义为是否参与跨店调拨功能。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_store_goods_Ex.custom_label_type IS '自定义标签类型(基于字段名和取值推测):2=使用自定义标签;1 可能表示使用系统默认标签。具体影响哪些标签功能需业务确认。 | 来源: custom_label_type';
+COMMENT ON COLUMN dim_store_goods_Ex.option_required IS '是否需要额外选项或规格(基于字段名和取值推测):1=不需要额外选项,按单规格销售;其他值可能表示必须选择配料或口味。当前样本全部为 1。 | 来源: option_required';
+COMMENT ON COLUMN dim_store_goods_Ex.remark IS '商品备注,可填写口味说明、供应商信息、注意事项等;当前样本全部为空。 | 来源: remark';
+COMMENT ON COLUMN dim_store_goods_Ex.sort_order IS '前端展示排序权重,控制商品在列表中的显示顺序,具体规则(数值越大还是越小排前)由业务配置决定。 | 来源: sort';
+
+-- dim_goods_category
+CREATE TABLE IF NOT EXISTS dim_goods_category (
+ category_id BIGINT,
+ tenant_id BIGINT,
+ category_name VARCHAR(50),
+ alias_name VARCHAR(50),
+ parent_category_id BIGINT,
+ business_name VARCHAR(50),
+ tenant_goods_business_id BIGINT,
+ category_level INTEGER,
+ is_leaf INTEGER,
+ open_salesman INTEGER,
+ sort_order INTEGER,
+ is_warehousing INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (category_id)
+);
+COMMENT ON COLUMN dim_goods_category.category_id IS '分类节点主键。来自分类树节点的 id,在整个商品分类维度内唯一。用于在事实表中作为商品分类外键引用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_goods_category.tenant_id IS '租户 ID(商户/品牌 ID)。当前所有节点取值相同,表示同一个租户下的分类树。事实表可通过该字段与租户维度或门店维度间接关联。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_name IS '分类名称。一级大类示例:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。二级子类示例:槟榔、皮头、球杆、其他、饮料、酒水、茶水、咖啡、加料、洋酒、果盘、面、小吃等。用于前台展示和报表按细分类统计。 | 来源: category_name';
+COMMENT ON COLUMN dim_goods_category.alias_name IS '分类别名。当前样例数据全部为空字符串,预留给业务方做简称或别名展示。对现阶段经营分析无影响。 | 来源: alias_name';
+COMMENT ON COLUMN dim_goods_category.parent_category_id IS '父级分类 ID。根节点取值为 0,表示没有父分类;子节点取值为父分类的 id。与 category_id 共同形成树形层级关系。 | 来源: pid | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.business_name IS '业务大类名称。将多个细分类归入同一业务线。观测值与一级大类相同:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。子类的 business_name 继承所属根节点的大类名称。用于按业务线汇总库存和销售。 | 来源: business_name';
+COMMENT ON COLUMN dim_goods_category.tenant_goods_business_id IS '业务大类 ID。每个 business_name 对应唯一一个 tenant_goods_business_id,根节点和其下所有子节点共享同一取值。例如“酒水”大类及其子类饮料、茶水、咖啡、加料、洋酒拥有相同的业务 ID。可作为外键连接“业务线维度表”。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_level IS '分类层级:1 表示一级大类(pid = 0),2 表示二级子类(pid ≠ 0)。方便在报表中区分大类与子类进行分组和展示层级控制。 | 来源: 由 pid 推导';
+COMMENT ON COLUMN dim_goods_category.is_leaf IS '是否叶子节点:1 表示叶子分类(categoryBoxes 为空列表),0 表示非叶子分类(存在子分类)。当前样例数据中,一级大类是非叶子节点,二级分类是叶子节点。用于树状导航或限制只能在叶子分类建商品。 | 来源: 由 categoryBoxes 推导';
+COMMENT ON COLUMN dim_goods_category.open_salesman IS '营业员开关控制。枚举含义根据业务系统定义,一般设计为:1 表示启用营业员/导购相关功能,2 表示关闭或不启用。当前样例所有分类取值为 2,说明这一套分类在库存模块中统一未启用营业员逻辑。对目前的经营分析影响较小。 | 来源: open_salesman';
+COMMENT ON COLUMN dim_goods_category.sort_order IS '分类排序序号。来自 sort 字段,用于前端展示顺序控制,数值越小越靠前。当前大部分分类为 0,仅少数为 1,说明排序配置较为粗略。对指标统计无实质影响。 | 来源: sort';
+COMMENT ON COLUMN dim_goods_category.is_warehousing IS '是否参与库存管理。枚举:1 表示参与库存管理,0 表示不参与(如服务类商品、手工费用)。当前文件中所有分类取值为 1,表示这一份分类树只包含“走库存”的商品分类。可在库存报表中用作过滤条件。 | 来源: is_warehousing';
+
+-- dim_groupbuy_package
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
+ groupbuy_package_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ package_name VARCHAR(200),
+ package_template_id BIGINT,
+ selling_price NUMERIC(10,2),
+ coupon_face_value NUMERIC(10,2),
+ duration_seconds INTEGER,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ table_area_name VARCHAR(100),
+ is_enabled INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ tenant_table_area_id_list VARCHAR(512),
+ card_type_ids VARCHAR(255),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_id IS '租户(品牌/商户)ID。本数据集中全表相同,表示同一品牌。 | 来源: tenant_id | 角色: 外键(指向租户维)';
+COMMENT ON COLUMN dim_groupbuy_package.site_id IS '门店 ID,本表所有记录属于同一门店。与其他 JSON 的 site_id 一致。 | 来源: site_id | 角色: 外键(指向门店维)';
+COMMENT ON COLUMN dim_groupbuy_package.package_name IS '团购套餐名称,用于前台展示及核销界面,例如“早场特惠一小时”“KTV欢唱四小时”等。 | 来源: package_name';
+COMMENT ON COLUMN dim_groupbuy_package.package_template_id IS '上层套餐 ID 或总部/系统级套餐 ID。多个 groupbuy_package_id 可能共享同一个 package_template_id,表示同一业务套餐在不同门店或不同版本下的配置。 | 来源: package_id | 角色: 外键(指向套餐模板维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.selling_price IS '团购售卖价,面向顾客在外部平台的成交价格。当前样本全部为 0,实际平台售价可能在外部系统,不在本地落地。 | 来源: selling_price';
+COMMENT ON COLUMN dim_groupbuy_package.coupon_face_value IS '券面值或内部结算面值。表示此套餐在门店侧可以抵扣的金额,用于验券或套餐流水时记账。例如“早场特惠一小时”可配置为 40.00,“KTV欢唱四小时”可配置为 200.00。当前样本为 0 但字段设计上非常关键。 | 来源: coupon_money';
+COMMENT ON COLUMN dim_groupbuy_package.duration_seconds IS '套餐包含的时长,单位为秒。常见取值:3600 表示 1 小时,7200 表示 2 小时,14400 表示 4 小时。核销时可用于换算可用台费时长。 | 来源: duration';
+COMMENT ON COLUMN dim_groupbuy_package.start_time IS '套餐整体生效开始时间。例如“2025-07-20 00:00:00”。通常从某日零点开始。 | 来源: start_time';
+COMMENT ON COLUMN dim_groupbuy_package.end_time IS '套餐整体生效结束时间。在该时间点之后不可使用。极大日期(如 9999-12-31 23:59:59)可视为长期有效。 | 来源: end_time';
+COMMENT ON COLUMN dim_groupbuy_package.table_area_name IS '套餐适用的门店台区名称,例如“A区中八”“B区中八”“斯诺克”“包厢”“KTV”等。主要用于展示和过滤,配合区域 ID 列实现人类可读的说明。 | 来源: table_area_name';
+COMMENT ON COLUMN dim_groupbuy_package.is_enabled IS '启用状态枚举。1 表示启用或上架;2 表示停用或下架。侧重表示“配置是否上架”,与 effective_status 区分。 | 来源: is_enabled';
+COMMENT ON COLUMN dim_groupbuy_package.is_delete IS '逻辑删除标志。0 表示正常;1 表示逻辑删除(数据仍保留但不再使用)。当前样本全部为 0。 | 来源: is_delete';
+COMMENT ON COLUMN dim_groupbuy_package.create_time IS '套餐配置在系统中的创建时间,用于审计和版本追踪。 | 来源: create_time';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_table_area_id_list IS '租户级台区分组 ID 列表。当前每条记录为一个大整数(例如 2791960001957765)字符串,表示“台区分组”主键。系统通过此分组再关联到具体多个台区。 | 来源: tenant_table_area_id_list | 角色: 外键(指向台区分组维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.card_type_ids IS '允许使用本套餐的会员卡类型 ID 列表。当前样本统一为字符串“0”,表示未限制卡种,任意顾客或任意会员卡都可使用。若未来启用,将以分隔的 ID 列表形式记录限定卡种。 | 来源: card_type_ids | 角色: 外键(潜在指向卡种维)';
+
+-- dim_groupbuy_package_Ex
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
+ groupbuy_package_id BIGINT,
+ site_name VARCHAR(100),
+ usable_count INTEGER,
+ date_type INTEGER,
+ usable_range VARCHAR(255),
+ date_info VARCHAR(255),
+ start_clock VARCHAR(16),
+ end_clock VARCHAR(16),
+ add_start_clock VARCHAR(16),
+ add_end_clock VARCHAR(16),
+ area_tag_type INTEGER,
+ table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_area_id_list VARCHAR(512),
+ group_type INTEGER,
+ system_group_type INTEGER,
+ package_type INTEGER,
+ effective_status INTEGER,
+ max_selectable_categories INTEGER,
+ creator_name VARCHAR(100),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package_Ex.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.site_name IS '门店名称,当前均为“朗朗桌球”。属于冗余展示字段,可用于报表标题。 | 来源: site_name';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_count IS '可使用次数上限。当前全部为 9999999,用作“无限次使用”的哨兵值。若未来限制次数,只需配置为具体次数。 | 来源: usable_count';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_type IS '日期限制类型枚举。当前样本全部为 1。推测常见含义:1 表示“全部日期可用”;其他值可用于区分工作日、周末或指定日期等模式。 | 来源: date_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_range IS '日期范围说明的文本,例如“周一至周五”等。当前全部为空字符串,实际规则由 date_type 与时间段字段控制。 | 来源: usable_range';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_info IS '更细粒度的日期信息,可能用于存储具体日期列表或节假日规则,形式可能是编码或 JSON 字符串。当前几乎全部为空,仅有极少记录为“0”。 | 来源: date_info';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.start_clock IS '每日可用时间段的起始时间(第一段),字符串格式 HH:MM:SS,例如“10:00:00”“00:00:00”。与 end_clock 组合定义日内时段。 | 来源: start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.end_clock IS '每日可用时间段的结束时间(第一段),字符串格式 HH:MM:SS。与 start_clock 共同描述第一段可用时段。 | 来源: end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_start_clock IS '附加可用时段的起始时间(第二段),格式 HH:MM:SS。当前样本常见值为“00:00:00”或“10:00:00”。用于配置早场加夜场等双时段场景。 | 来源: add_start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_end_clock IS '附加可用时段的结束时间(第二段)。常见值如“1.00:00:00”“18:00:00”“23:59:00”。其中“1.00:00:00”表示跨至次日零点,用于表示“可用到第二天凌晨”的场景。 | 来源: add_end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.area_tag_type IS '区域标记类型枚举。当前样本全部为 1。推测 1 表示“按台区标签限制”(如 A 区、B 区、中八、斯诺克、包厢、KTV 等)。其他取值可能对应按具体台桌或其它规则限用。 | 来源: area_tag_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id IS '单一台区 ID。当前样本全部为 0。原始设计用于限定只能在一个具体区域使用,但由于已引入多选逻辑,实际使用已迁移到 tenant_table_area_id_list。 | 来源: table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.tenant_table_area_id IS '租户级台区 ID,单值版本。当前样本全部为 0。与 table_area_id 类似,已被多选列表字段取代。 | 来源: tenant_table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id_list IS '门店级台区 ID 列表。当前样本全部为空字符串。根据命名推测原本用于存储多个 table_area_id,实际实现已转向租户维度列表字段。 | 来源: table_area_id_list';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.group_type IS '团购类型枚举。当前样本全部为 1。推测 1 表示“计时类/台费类套餐”。其他取值可能用于商品类套餐、代金券类等,需结合系统配置进一步确认。 | 来源: group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.system_group_type IS '系统级团购类型枚举。当前样本全部为 1。推测 1 表示“券码类团购”,即通过券码核销。其他取值可能为卡内套餐、内部套餐等,具体含义有待业务确认。 | 来源: system_group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.package_type IS '内部业务子类型枚举。样本中取值有 1 与 2,各占比不同。具体含义不明,可能区分不同产品线或套餐来源,例如“平台合作套餐”与“自定义套餐”等,需要参考业务文档。 | 来源: type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.effective_status IS '当前有效状态枚举,由系统根据时间及配置动态计算。观测值:1 表示当前有效,可正常核销;3 表示失效或已过期(即使 is_enabled 仍为 1,也不可使用)。可用于分析时过滤失效套餐。 | 来源: effective_status';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.max_selectable_categories IS '最大可选择分类数或子项数,具体含义未在样本和说明中体现,当前值全部为 0。可能用于“组合型套餐”中限制可选项目数量。 | 来源: max_selectable_categories';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.creator_name IS '创建人名称,例如“店长:郑丽珊”。主要用于审计追踪和后台展示。 | 来源: creator_name';
+
+-- dwd_settlement_head
+CREATE TABLE IF NOT EXISTS dwd_settlement_head (
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_name VARCHAR(100),
+ table_id BIGINT,
+ settle_name VARCHAR(100),
+ order_trade_no BIGINT,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ settle_type INTEGER,
+ revoke_order_id BIGINT,
+ member_id BIGINT,
+ member_name VARCHAR(100),
+ member_phone VARCHAR(50),
+ member_card_account_id BIGINT,
+ member_card_type_name VARCHAR(100),
+ is_bind_member BOOLEAN,
+ member_discount_amount NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ pay_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head.tenant_id IS '租户/商户 ID(品牌维度),与各业务 JSON 中的 tenantId 一致。 | 来源: settleList.tenantId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_id IS '门店 ID,用于关联门店维表 dim_site。 | 来源: settleList.siteId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_name IS '门店名称快照,冗余展示字段,推荐通过 site_id 关联维表获取标准名称。 | 来源: settleList.siteName';
+COMMENT ON COLUMN dwd_settlement_head.table_id IS '结账关联的桌台 ID,对应台桌维表 dim_site_table 的主键。 | 来源: settleList.tableId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.settle_name IS '结账对象名称,一般为 “区域 + 桌号”,如 “A区 A17”,便于报表展示。 | 来源: settleList.settleName';
+COMMENT ON COLUMN dwd_settlement_head.order_trade_no IS '交易号 / 订单流水号,与台费、助教等明细中的 order_trade_no 一致,用于按“交易维度”串联各业务明细。 | 来源: settleList.settleRelateId';
+COMMENT ON COLUMN dwd_settlement_head.create_time IS '结账创建时间(收银端点击“确认结账”的时间),格式:YYYY-MM-DD HH:MM:SS。 | 来源: settleList.createTime';
+COMMENT ON COLUMN dwd_settlement_head.pay_time IS '实际支付完成时间,通常晚于 create_time,用于资金结算及对账分析。 | 来源: settleList.payTime';
+COMMENT ON COLUMN dwd_settlement_head.settle_type IS '结账类型枚举。样本中主要有:1=正常结账;3=特殊类型结账(如挂账、补单、调整单等,具体需业务确认)。 | 来源: settleList.settleType';
+COMMENT ON COLUMN dwd_settlement_head.revoke_order_id IS '若当前记录属于撤销链路,记录对应的撤销单或原单的结账 ID,形成自关联关系。样本中为 0。 | 来源: settleList.revokeOrderId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_id IS '会员主键 ID,一般对应租户维度的会员 ID,用于关联 dim_member。 | 来源: settleList.memberId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_name IS '会员姓名快照,冗余展示字段;当前样本多为空,推荐通过关联会员维表获取标准姓名。 | 来源: settleList.memberName';
+COMMENT ON COLUMN dwd_settlement_head.member_phone IS '会员手机号快照,冗余展示字段,通常通过会员维表获取更可靠。 | 来源: settleList.memberPhone';
+COMMENT ON COLUMN dwd_settlement_head.member_card_account_id IS '会员卡账户 ID,对应 dim_member_card_account 主键;当前样本多为 0,但结构上是“结账 → 具体卡账户”的外键。 | 来源: settleList.tenantMemberCardId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_card_type_name IS '会员卡类型名称快照,如“储值卡”“次卡”等,便于前端展示和报表查看。 | 来源: settleList.memberCardTypeName';
+COMMENT ON COLUMN dwd_settlement_head.is_bind_member IS '本单是否绑定会员。0=否(散客);1=是(存在 member_id)。样本中多为 0。 | 来源: settleList.isBindMember';
+COMMENT ON COLUMN dwd_settlement_head.member_discount_amount IS '会员折扣产生的优惠金额(元),例如会员卡折扣减免的台费/商品金额,参与整单优惠拆分。 | 来源: settleList.memberDiscountAmount';
+COMMENT ON COLUMN dwd_settlement_head.consume_money IS '本次结账消费总额(原价小计),约等于台费 + 商品 + 助教 + 服务等项目原价金额之和,未扣除任何优惠。 | 来源: settleList.consumeMoney';
+COMMENT ON COLUMN dwd_settlement_head.table_charge_money IS '本单台费(桌台计费部分)的金额(原价侧)。 | 来源: settleList.tableChargeMoney';
+COMMENT ON COLUMN dwd_settlement_head.goods_money IS '本单商品销售原价金额,对应酒水、小吃等商品类消费。 | 来源: settleList.goodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.real_goods_money IS '商品实际计入金额,通常为 goods_money 扣除部分促销/折扣之后的金额。 | 来源: settleList.realGoodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_pd_money IS '助教“排钟 / 点钟 / 按时长服务”等项目的应计金额(原价侧),与助教流水中的 ledger_amount 汇总对应。 | 来源: settleList.assistantPdMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_cx_money IS '助教“超休”类助教项目金额(原价侧),是对助教收入的补充拆分维度,具体业务定义需结合助教模块确认。 | 来源: settleList.assistantCxMoney';
+COMMENT ON COLUMN dwd_settlement_head.adjust_amount IS '手动减免,人工调价金额汇总(整单减免或特殊价格调整),通常正值表示减免额度。 | 来源: settleList.adjustAmount';
+COMMENT ON COLUMN dwd_settlement_head.pay_amount IS '本单顾客“实付金额”(不含券面值这类虚拟抵扣),等于各支付渠道金额之和减去退款等调整。 | 来源: settleList.payAmount';
+COMMENT ON COLUMN dwd_settlement_head.balance_amount IS '从会员储值余额账户中扣除的金额(储值卡消费部分)。 | 来源: settleList.balanceAmount';
+COMMENT ON COLUMN dwd_settlement_head.recharge_card_amount IS '充值卡支付金额(使用充值类卡片余额支付的金额),与储值/充值型卡资金来源相关。 | 来源: settleList.rechargeCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.gift_card_amount IS '礼品卡或代金卡支付金额。 | 来源: settleList.giftCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.coupon_amount IS '本单由优惠券(团购券、代金券等)实际抵扣的金额。 | 来源: settleList.couponAmount';
+COMMENT ON COLUMN dwd_settlement_head.rounding_amount IS '抹零 / 四舍五入产生的金额差值,例如按角、分抹零。 | 来源: settleList.roundingAmount';
+COMMENT ON COLUMN dwd_settlement_head.point_amount IS '积分相关金额或数量。根据系统配置可能表示“使用积分抵扣的金额”或“本单获得的积分折算金额”,文档未给出唯一定义。 | 来源: settleList.pointAmount';
+
+-- dwd_settlement_head_Ex
+CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
+ order_settle_id BIGINT,
+ serial_number INTEGER,
+ settle_status INTEGER,
+ can_be_revoked BOOLEAN,
+ revoke_order_name VARCHAR(100),
+ revoke_time TIMESTAMPTZ,
+ is_first_order BOOLEAN,
+ service_money NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ payment_method INTEGER,
+ coupon_sale_amount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ is_activity BOOLEAN,
+ operator_name VARCHAR(100),
+ salesman_name VARCHAR(100),
+ order_remark VARCHAR(255),
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.serial_number IS '结账序列号或打印序号,当前样本全部为 0,具体业务用途未在文档中明确。 | 来源: settleList.serialNumber';
+COMMENT ON COLUMN dwd_settlement_head_Ex.settle_status IS '结账状态枚举。当前样本值均为 2,表示“已结算/已完成”;其他取值及含义未在样本和文档中出现,需后续补充。 | 来源: settleList.settleStatus';
+COMMENT ON COLUMN dwd_settlement_head_Ex.can_be_revoked IS '本单是否仍允许撤销/冲正。0=否;1=是。样本中均为 0。主要用于运维控制,分析价值有限。 | 来源: settleList.canBeRevoked';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_order_name IS '撤销单名称/标识,用于人工识别撤销关系;当前样本为空。 | 来源: settleList.revokeOrderName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_time IS '撤销时间。无撤销时通常为系统默认值(如 0001-01-01 00:00:00)。 | 来源: settleList.revokeTime';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_first_order IS '是否首单(新客首单)标记。0=否;1=是。当前样本全部为 0,且文档中说明为“推测用途”,具体业务定义需确认。 | 来源: settleList.isFirst';
+COMMENT ON COLUMN dwd_settlement_head_Ex.service_money IS '其他服务费金额(如包间服务费等),用于与台费、商品、助教金额区分。 | 来源: settleList.serviceMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.cash_amount IS '现金支付金额。 | 来源: settleList.cashAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.card_amount IS '刷卡类支付金额(如银行卡/信用卡等),具体包含哪些通道需结合支付模块确认。 | 来源: settleList.cardAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.online_amount IS '线上支付金额汇总(如微信、支付宝、云闪付等),不区分具体通道。 | 来源: settleList.onlineAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.refund_amount IS '本单涉及的退款金额(元)。普通正常结账为 0,退单或部分退款时为正数。 | 来源: settleList.refundAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.prepay_money IS '本单使用的预付金/定金金额。 | 来源: settleList.prepayMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.payment_method IS '支付方式整体标记(枚举)。当前样本值统一为 0,具体各枚举值对应的支付方式未在文档中说明,需业务确认。 | 来源: settleList.paymentMethod';
+COMMENT ON COLUMN dwd_settlement_head_Ex.coupon_sale_amount IS '优惠券本身的售卖金额/成本金额(例如顾客为购买套餐券支付的金额),当前样本多为 0。 | 来源: settleList.couponSaleAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.all_coupon_discount IS '所有券类优惠折扣的汇总金额,用于统计“券优惠总额”。 | 来源: settleList.allCouponDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.goods_promotion_money IS '商品促销产生的优惠金额(如满减、买赠均摊到商品部分)。 | 来源: settleList.goodsPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_promotion_money IS '助教项目参与活动/促销产生的优惠金额。 | 来源: settleList.assistantPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.activity_discount IS '整单活动折扣金额(如整单打折、满减活动产生的优惠),不区分具体项目类别。 | 来源: settleList.activityDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_manual_discount IS '针对助教服务的人工减免金额,与一般商品/台费折扣区分开。 | 来源: settleList.assistantManualDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_price IS '积分抵扣对应的金额(售价侧),记录因积分使用而减少的应收金额。 | 来源: settleList.pointDiscountPrice';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_cost IS '积分抵扣对应的成本金额(成本侧),用于毛利和利润分析。 | 来源: settleList.pointDiscountCost';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_coupon IS '是否使用优惠券。0=未使用;1=使用。当前样本均为 0。 | 来源: settleList.isUseCoupon';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_discount IS '是否使用折扣(包括会员折扣或其他整单折扣)。0=未使用;1=使用。当前样本多为 0。 | 来源: settleList.isUseDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_activity IS '是否参与营销活动。0=未参与;1=参与。 | 来源: settleList.isActivity';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_name IS '结账操作员名称快照(通常带角色前缀,如“收银员:张三”),用于报表展示。 | 来源: settleList.operatorName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_name IS '营业员/业务员名称,用于业绩归属及提成分析;样本中多为空。 | 来源: settleList.salesManName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_remark IS '订单备注,由收银员手工填写的文字说明,如特殊情况、赠送原因等,主要用于人工复盘。 | 来源: settleList.orderRemark';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_id IS '结账操作员用户 ID,用于关联员工/账号维度(如 dim_staff)。 | 来源: settleList.operatorId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_user_id IS '营业员用户 ID,可关联员工维度,用于业绩分析和提成计算。 | 来源: settleList.salesManUserId | 角色: 外键';
+
+-- dwd_table_fee_log
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
+ table_fee_log_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ member_id BIGINT,
+ ledger_name VARCHAR(64),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ real_table_charge_money NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ real_table_use_seconds INTEGER,
+ add_clock_seconds INTEGER,
+ start_use_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log.order_trade_no IS '订单交易号。整笔订单的主编号,用于把同一订单下的台费、商品、助教等多种明细串联在一起。可与支付记录中的交易号对应。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_settle_id IS '结算单号 / 结账 ID。对应一次完整的结账操作。与 dwd_settlement_head 的主键关联。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_pay_id IS '订单支付记录 ID。对应支付记录中的 id 或 relate_id(视具体模型)。用于追踪这条台费最终对应哪一条支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_id IS '租户 / 品牌 ID。本文件内所有记录属于同一租户。与其他表的 tenant_id 一致,用于品牌级过滤。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_id IS '门店 ID。当前样本为同一门店。与嵌套的 siteProfile.id 以及其他 JSON 中的 site_id 对应,用于门店维度关联。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_id IS '桌台 ID。对应“台桌基础表”的主键。用于确定具体哪一张台或包厢。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_id IS '门店内“台桌区域” ID(门店视角的区域,如 A 区、B 区、斯诺克区、包厢区)。与门店内部的区域维度对应。 | 来源: site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_name IS '台桌区域名称,如 “A区”“B区”“斯诺克区”“VIP包厢” 等。主要用于报表展示和人工阅读。 | 来源: site_table_area_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_table_area_id IS '租户层面的台桌区域 ID。用于品牌层统一定义的区域配置(一个区域可在多门店复用)。对应租户级区域维度。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.member_id IS '会员 ID。多数为 0 表示散客。非 0 时表示关联会员:0 表示散客或未使用会员;>0 对应会员档案中的 id。用于将台费流水关联到 dim_member。 | 来源: member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_name IS '台号名称,例如 “A1”“A2”“S1”“VIP包厢” 等。等价于桌台维表中的展示名称,冗余在流水中作为快照。 | 来源: ledger_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_unit_price IS '台费结算时的计费单价(元/小时或元/单位时长)。与 ledger_count 配合计算原始应收台费。常见值如 48.0、58.0、68.0、88.0、98.0、116.0 等。 | 来源: ledger_unit_price | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_count IS '计费时长单位数。与 ledger_unit_price 共同决定原始应收额。可与 real_table_use_seconds 换算关系约为:时长秒数 ≈ ledger_count × 计费粒度(例如 30 分钟、60 分钟)。 | 来源: ledger_count | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_amount IS '原始应收台费金额,按单价与计费时长计算出来的台费金额,尚未考虑会员、券、调账等各类优惠拆分。 | 来源: ledger_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_charge_money IS '实际向顾客收取的台费金额(现金 / 实付维度),不含券方承担、会员承担和内部调账部分。若为 0,则该笔台费完全由券、会员或内部调账承担。 | 来源: real_table_charge_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.coupon_promotion_amount IS '由优惠券、活动、团购等促销承担的优惠金额,直接抵扣在台费上。常见值为与单价或整倍数相同,例如 48.0、96.0、136.0、144.0 等。若 real_table_charge_money 为 0 且该字段等于 ledger_amount,说明台费完全由促销承担。 | 来源: coupon_promotion_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.member_discount_amount IS '由会员权益产生的优惠金额,例如会员折扣、会员免费台等。若 ledger_amount = real_table_charge_money = member_discount_amount,表示这笔台费由会员权益承担,但仍作为台费收入进行记录。 | 来源: member_discount_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.adjust_amount IS '手动减免,调整金额 / 调账金额。用于将台费金额转移或冲减到其他项目(例如套餐、包厢统一计费)或做手工调整。若 ledger_amount 完全被 adjust_amount 抵消,则说明该笔台费被整体调出当前台费科目。 | 来源: adjust_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_use_seconds IS '台费实际计费时长(秒)。用于计算台费单价与费率分析。内部统一以秒为单位。 | 来源: real_table_use_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.add_clock_seconds IS '加钟时长(秒)。在原有使用基础上追加的累计加钟时长,常见为 2400、4200 等 60 的倍数(对应 40 分钟、70 分钟等)。 | 来源: add_clock_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.start_use_time IS '台开始使用时间,即实际开台时间。与 ledger_start_time 相同,表示计费起算点。 | 来源: start_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_end_time IS '台账计费结束时间。通常与 last_use_time 相差 1 秒。可理解为系统为计费进行的截断时刻。 | 来源: ledger_end_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.create_time IS '台费流水记录创建时间,通常接近结账时间。用于区分计费期间与结账时间。 | 来源: create_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_status IS '台费状态。样本中全部为 1。含义:1 表示正常已结算台费。按命名推断,0 可能表示未结算,2 可能表示作废或撤销,需要结合后续数据确认。 | 来源: ledger_status | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_single_order IS '是否独立计费单元。枚举:1 表示该记录是独立结算的桌费;0 表示非独立结算条目(可能是合并结账、转台过程中的占位记录)。is_single_order = 0 的记录通常 ledger_count 与 real_table_use_seconds 为 0。 | 来源: is_single_order | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_delete IS '逻辑删除标志。0 表示未删除(有效记录);1 表示已逻辑删除(一般不参与统计)。当前样本全部为 0。 | 来源: is_delete | 角色: 无';
+
+-- dwd_table_fee_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
+ table_fee_log_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_name VARCHAR(64),
+ used_card_amount NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ ledger_start_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ salesman_org_id BIGINT,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log_Ex.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_name IS '操作员姓名。为冗余展示字段,便于直接阅读而不必联表员工档案。 | 来源: operator_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_name IS '营业员姓名。当前样本为空。用于需要对营业员维度做业绩统计时作为冗余展示。 | 来源: salesman_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.used_card_amount IS '由储值卡、次卡等“卡内余额”直接抵扣到台费的金额。当前样本为 0,但语义明确,用于区分“卡扣款”与“现金收款”。 | 来源: used_card_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.service_money IS '服务费 / 成本 /分成金额字段,类似助教流水里的 service_money。当前样本全为 0,门店未启用该字段,未来可能用于台费附加服务费或分成计算。 | 来源: service_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.mgmt_fee IS '管理费字段。当前样本为 0。推测用于未来支持“台费附加管理费”功能。尚未实际启用。 | 来源: mgmt_fee | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.fee_total IS '附加费用合计值字段。当前样本为 0。设计上用于汇总管理费、服务费等附加费用。尚未实际启用。 | 来源: fee_total | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.ledger_start_time IS '台账计费起始时间。当前样本与 start_use_time 相同,表示计费与开台同时开始。 | 来源: ledger_start_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.last_use_time IS '最后使用 / 操作时间,通常略晚于 ledger_end_time。可视为客人最后一次用台或最后一次加钟/操作的时间点。 | 来源: last_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_id IS '操作员 ID。负责开台 / 结账的员工账号 ID。与员工 / 账号体系中的用户 ID 对应。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_user_id IS '营业员用户 ID。目前样本值为 0,表示门店暂未使用此字段做提成员工归属,但语义清晰。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_org_id IS '营业员所属机构 / 部门 ID。目前样本为 0。用于员工组织结构统计时的归属。 | 来源: salesman_org_id | 角色: 外键';
+
+-- dwd_table_fee_adjust
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
+ table_fee_adjust_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ ledger_amount NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ adjust_time TIMESTAMPTZ,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_trade_no IS '订单交易号;与台费流水、结账记录等表中的同名字段一致,用于把本次台费调整挂到具体订单上。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_settle_id IS '结算单 / 小票 ID;与小票、结账头表中的 order_settle_id 对应,用于关联同一次结账。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_id IS '租户 / 品牌 ID;标识该记录属于哪一个商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.site_id IS '门店 ID;与 dim_site、其它业务事实表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_id IS '台桌 ID;与 dim_table(site_tables_master.id)以及各类台费、助教流水中的 site_table_id 对应,标识哪一张台发生了折扣/调账。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_id IS '门店维度的台桌区域 ID;与 dim_table 中的 site_table_area_id 对应,例如 “斯诺克区”“VIP包厢”等区域。 | 来源: tableProfile.site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_name IS '台桌区域名称快照,例如 “斯诺克区”“A区”“VIP包厢”;冗余展示字段,可从 dim_table 通过 table_area_id 获取。 | 来源: tableProfile.site_table_area_name';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_table_area_id IS '租户维度的“台桌区域 ID”;同一租户下跨门店复用的区域标识,用于在租户级别统计各区域的折扣分布。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_amount IS '台费调整金额;等于台费流水中对应记录的 adjust_amount。正数表示被减免/调账掉的台费金额(本批数据全部为正);是衡量台费折扣规模的核心度量。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_status IS '调整记录状态(枚举)。1:生效调整(当前有效的折扣/调账记录);0:失效/被覆盖的历史记录(同一订单有多次调整时,旧记录会标记为 0,仅最新一条为 1)。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_table_fee_adjust.is_delete IS '逻辑删除标记(枚举)。0:未删除(有效记录);1:已逻辑删除(后台标记删除,不再参与业务统计)。当前数据全部为 0,但字段需保留以适配长期数据。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_table_fee_adjust.adjust_time IS '台费调整记录创建时间,即打折/调账操作被系统写入的时间戳,用于时间分析和与结账时间对比(判断是事前折扣还是事后调账)。 | 来源: create_time';
+
+-- dwd_table_fee_adjust_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
+ table_fee_adjust_id BIGINT,
+ adjust_type INTEGER,
+ ledger_count INTEGER,
+ ledger_name VARCHAR(128),
+ applicant_name VARCHAR(64),
+ operator_name VARCHAR(64),
+ applicant_id BIGINT,
+ operator_id BIGINT,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.adjust_type IS '调整类型(枚举)。当前数据全部为 1。取值示例:1:台费打折 / 台费减免(本门店实际使用的唯一类型);其他值:预留给台费转移、误操作恢复等其他类型(当前未出现,仅推测)。 | 来源: adjust_type';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_count IS '调整次数计数,本数据中恒为 1,表示“一次调整事件”;与台费流水中的 ledger_count(计时长)含义不同。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_name IS '调账项目名称或打折原因名称(设计意图);当前门店所有记录值为空字符串,未实际使用。作用暂不明确,保留以备后续业务启用。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_name IS '申请人姓名快照,通常包含角色前缀(如 “收银员:张三”);是 applicant_id 的冗余展示字段,实际名称应以员工维表为准。 | 来源: applicant_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_name IS '操作员姓名快照;与 operator_id 对应的姓名冗余字段。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_id IS '申请人 ID;发起本次台费折扣/调账的员工账号 ID,用于按员工维度统计折扣行为。 | 来源: applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_id IS '实际执行调账操作的操作员 ID;当前样本中与 applicant_id 相同,但模型上允许“申请人 ≠ 操作人”。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_store_goods_sale
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
+ store_goods_sale_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_goods_id BIGINT,
+ site_id BIGINT,
+ tenant_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ site_table_id BIGINT,
+ ledger_name VARCHAR(200),
+ ledger_group_name VARCHAR(100),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (store_goods_sale_id)
+);
+COMMENT ON COLUMN dwd_store_goods_sale.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_trade_no IS '订单交易号(业务单号);与台费、助教、团购等表的 order_trade_no 一致,用于把同一订单下各类消费串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_settle_id IS '结账记录主键 ID;连接结账记录 / 结算头事实表。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_pay_id IS '支付记录 ID;连接支付流水事实表,用于还原本条销售对应的收款信息。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_goods_id IS '当前版本的订单内商品明细 ID;可在订单范围内唯一定位该商品行,用于与小票明细等做行级关联。 | 来源: order_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_id IS '门店 ID(系统主键);与其它流水表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_id IS '租户/品牌 ID;同一品牌下多门店共享同一个 tenant_id。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_goods_id IS '门店级商品 ID;连接门店商品档案 dim_store_goods,与库存变动记录中的 siteGoodsId 一致。 | 来源: site_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_id IS '租户级(品牌级)商品 ID;连接租户级商品档案维度表,一个 tenant_goods_id 在不同门店可对应多个 site_goods_id。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_category_id IS '租户级商品一级分类 ID;连接商品分类维度(如酒水、零食等)。 | 来源: tenant_goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_business_id IS '租户级商品业务大类 ID(更高一层的业务分类,如“零食类”“酒水类”等)。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_table_id IS '球台 ID;非 0 表示该商品在某张台桌上点单,0 表示前台售卖或与台桌无关。连接台桌维度 dim_table。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_name IS '销售项目名称(商品名),如“哇哈哈矿泉水”“地道肠”等;为当时销售时刻的名称快照。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_group_name IS '门店前台菜单分组名称,如“酒水”“零食”“小吃”等;与品牌统一分类是两套维度。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_unit_price IS '结算单价(元/单位);本次销售实际使用的单价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_count IS '销售数量(以商品单位计),如 1、2、6、36 等。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_amount IS '原始应收金额(未考虑任何折扣/抵扣),通常接近 ledger_unit_price × ledger_count。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_store_goods_sale.discount_price IS '折后单价(元/单位);无折扣时等于 ledger_unit_price,有折扣时小于 ledger_unit_price。 | 来源: discount_price';
+COMMENT ON COLUMN dwd_store_goods_sale.real_goods_money IS '本行商品实际入账金额(已考虑折扣及其他抵扣后,实际计入营业额的金额);一定不大于 ledger_amount。 | 来源: real_goods_money';
+COMMENT ON COLUMN dwd_store_goods_sale.cost_money IS '本行商品对应的成本金额,用于毛利和利润分析;源自商品档案成本价及成本核算逻辑。 | 来源: cost_money';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_status IS '销售流水状态:1=正常有效;其他数值(当前数据未出现)一般表示“待结算”“作废”等。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_store_goods_sale.is_delete IS '逻辑删除标志:0=正常有效;1=已删除(仅保留历史,不再参与前端展示及统计)(本批数据全部为 0)。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_store_goods_sale.create_time IS '销售记录创建时间,通常为结账时间或录入时间;用于时间维度分析,与订单层时间字段对齐。 | 来源: create_time';
+
+-- dwd_store_goods_sale_Ex
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
+ store_goods_sale_id BIGINT,
+ legacy_order_goods_id BIGINT,
+ site_name TEXT,
+ legacy_site_id BIGINT,
+ goods_remark TEXT,
+ option_value_name TEXT,
+ operator_name TEXT,
+ open_salesman_flag INTEGER,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ discount_money NUMERIC(18,2),
+ returns_number INTEGER,
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ package_coupon_id BIGINT,
+ order_coupon_id BIGINT,
+ member_coupon_id BIGINT,
+ option_price NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ is_single_order INTEGER,
+ sales_type INTEGER,
+ operator_id BIGINT
+);
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_order_goods_id IS '旧版订单商品明细 ID,兼容字段;当前接口已统一使用 order_goods_id,本批数据全部为 0。 | 来源: orderGoodsId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.site_name IS '门店名称,对 site_id 的冗余文本(例如“朗朗桌球”),用于展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_site_id IS '历史兼容门店 ID;当前接口统一使用 site_id,本批数据 siteId 全部为 0。 | 来源: siteId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.goods_remark IS '商品备注/口味说明/特殊说明;部分记录为空,部分与商品名相同。 | 来源: goods_remark';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_value_name IS '商品选项名称(规格/口味,如大杯/小杯、不加冰等);当前门店未启用多规格,样本中全部为空。 | 来源: option_value_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_name IS '操作员姓名冗余,如“收银员:郑丽珊”;用于展示,不作为关联键。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.open_salesman_flag IS '是否启用营业员机制标志:1=启用营业员/提成体系(需指定 salesman_* 字段);2=未启用营业员体系(本批数据全部为 2)。 | 来源: openSalesman';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_user_id IS '营业员用户 ID(系统账号 ID);当前样本全部为 0,说明门店未启用营业员业绩统计。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_name IS '营业员姓名;当前样本全部为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_role_id IS '营业员角色 ID(例如某角色代码对应“销售员”角色);当前样本全部为 0。 | 来源: salesman_role_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_org_id IS '营业员所属组织/部门 ID;当前样本全部为 0,未启用按组织分组统计。 | 来源: sales_man_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.discount_money IS '本行商品的直接价格优惠金额(打折让利部分);在简单场景下满足:ledger_amount − discount_money ≈ real_goods_money(不含积分、券抵扣)。 | 来源: discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.returns_number IS '退货数量;当前样本全部为 0,如发生退货则记录退回的件数。 | 来源: returns_number';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.coupon_deduct_money IS '优惠券/团购券直接抵扣到本条商品明细上的金额;当前样本为 0,说明券更多在订单级处理。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_discount_amount IS '由会员折扣针对本行商品产生的优惠金额;当前样本全部为 0,折扣通常体现在 discount_money 中。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money IS '由积分抵扣的金额(顾客用积分兑换的抵现金额)。 | 来源: point_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money_cost IS '积分抵扣对应的成本金额(积分成本、营销费用等核算用)。 | 来源: point_discount_money_cost';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.package_coupon_id IS '套餐券 ID;当商品来自套餐拆分或与套餐券关联时,用于追溯对应的套餐业务(当前样本为 0)。 | 来源: package_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.order_coupon_id IS '订单级优惠券 ID;整单使用某张券时,可用于记录该券对本行商品的分摊关系(当前样本为 0)。 | 来源: order_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_coupon_id IS '会员券 ID(如会员专享优惠券);当前样本为 0,为会员权益预留字段。 | 来源: member_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_price IS '商品选项(规格/加料等)的附加价格;当前门店未启用此功能,样本为 0。 | 来源: option_price';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_member_discount_money IS '由会员折扣作用在“选项价格”上的优惠金额;当前样本为 0。 | 来源: option_member_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_coupon_deduct_money IS '由优惠券抵扣“选项价格”的金额;当前样本为 0。 | 来源: option_coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.push_money IS '本行商品对应的提成金额(营业员/业务员提成);当前样本为 0,说明提成体系未启用。 | 来源: push_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.is_single_order IS '是否作为独立明细参与订单结算:1=作为独立明细参与订单;0=在特殊业务中可能合并为打包项目(当前样本全部为 1)。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.sales_type IS '销售类型:1=正常销售(当前样本全部为 1);常见扩展用法:2=赠品;3=内部消耗;4=盘点调整等。 | 来源: sales_type';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_id IS '操作员 ID(录入本条销售的员工);与其它流水中的 operator_id 一致,可统一做员工维度分析。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_assistant_service_log
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
+ assistant_service_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INTEGER,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ assistant_no VARCHAR(64),
+ nickname VARCHAR(64),
+ site_assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ person_org_id BIGINT,
+ assistant_level INTEGER,
+ level_name VARCHAR(64),
+ skill_id BIGINT,
+ skill_name VARCHAR(64),
+ ledger_unit_price NUMERIC(10,2),
+ ledger_amount NUMERIC(10,2),
+ projected_income NUMERIC(10,2),
+ coupon_deduct_money NUMERIC(10,2),
+ income_seconds INTEGER,
+ real_use_seconds INTEGER,
+ add_clock INTEGER,
+ create_time TIMESTAMPTZ,
+ start_use_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_trade_no IS '订单交易号,用于与台费、商品、支付等同一订单下的其他明细串联。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_settle_id IS '结算单号,对应结账记录、小票中的结算主键。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_pay_id IS '支付记录主键 ID,用于关联支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_id IS '订单中“助教项目明细”的内部 ID,一笔订单中多段助教服务时用于区分。 | 来源: order_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_type IS '助教服务类型枚举:1 表示常规助教服务(如基础课);2 表示附加类助教服务(如附加课);其他值预留。 | 来源: order_assistant_type';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_id IS '租户/品牌 ID,用于区分商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_id IS '门店 ID,对应门店维表中的门店主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_table_id IS '球台/包厢 ID,对应台桌维表主键。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_member_id IS '商户维度会员 ID,对应会员档案主键;0 表示非会员或散客。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.system_member_id IS '系统级会员 ID,用于跨门店识别同一会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_no IS '助教编号/工号,如 “27”;与助教档案中的工号一致。 | 来源: assistantNo';
+COMMENT ON COLUMN dwd_assistant_service_log.nickname IS '助教对外昵称,如“佳怡”“周周”;用于展示,不参与业务逻辑。 | 来源: nickname';
+COMMENT ON COLUMN dwd_assistant_service_log.site_assistant_id IS '门店维度助教 ID,对应助教账号维表主键。 | 来源: site_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.user_id IS '助教对应的系统用户 ID,对应账号体系中的 user_id。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_team_id IS '助教团队 ID,用于分组统计团队业绩。 | 来源: assistant_team_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.person_org_id IS '助教所属人事组织/部门 ID,如“助教部”;用于组织维度分析。 | 来源: person_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_level IS '助教等级编码:8=助教管理;10=初级;20=中级;30=高级;用于薪酬/评价分层。 | 来源: assistant_level | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.level_name IS '助教等级名称,与 assistant_level 对应,如“初级”“中级”“高级”“助教管理”。 | 来源: levelName';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_id IS '助教服务课程/技能 ID,应对应课程/技能配置表。 | 来源: skill_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_name IS '助教服务课程/技能名称,如“基础课”“附加课”。 | 来源: skillName';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_unit_price IS '助教服务标准单价(原价),例如按小时或按节课的标价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_amount IS '按标准单价计算的应收金额,近似等于 ledger_unit_price×计费时长换算后的金额。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_assistant_service_log.projected_income IS '实际计入门店收入的金额,已经考虑会员权益、券抵扣等后的结果。 | 来源: projected_income';
+COMMENT ON COLUMN dwd_assistant_service_log.coupon_deduct_money IS '由优惠券、团购券等直接抵扣到本次助教服务上的金额;0 表示未使用券。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_assistant_service_log.income_seconds IS '计费秒数(用于计算应收收入的时间长度),通常为按分钟取整的秒数。 | 来源: income_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.real_use_seconds IS '实际服务时长(秒),真实消耗的时间,用于分析助教工作量。 | 来源: real_use_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.add_clock IS '加钟秒数,在原有预约基础上临时增加的服务时间,数值为 60 的倍数。 | 来源: add_clock';
+COMMENT ON COLUMN dwd_assistant_service_log.create_time IS '助教流水记录创建时间,接近下单/结算时间。 | 来源: create_time';
+COMMENT ON COLUMN dwd_assistant_service_log.start_use_time IS '助教实际开始服务时间,通常与 ledger_start_time 一致。 | 来源: start_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.last_use_time IS '助教最后一次服务时间,通常与 ledger_end_time 一致。 | 来源: last_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.is_delete IS '逻辑删除标志:0 未删除;1 已逻辑删除,用于保留历史数据。 | 来源: is_delete';
+
+-- dwd_assistant_service_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
+ assistant_service_id BIGINT,
+ table_name VARCHAR(64),
+ assistant_name VARCHAR(64),
+ ledger_name VARCHAR(128),
+ ledger_group_name VARCHAR(128),
+ ledger_count INTEGER,
+ member_discount_amount NUMERIC(10,2),
+ manual_discount_amount NUMERIC(10,2),
+ service_money NUMERIC(10,2),
+ returns_clock INTEGER,
+ ledger_start_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_confirm INTEGER,
+ is_single_order INTEGER,
+ is_not_responding INTEGER,
+ is_trash INTEGER,
+ trash_applicant_id BIGINT,
+ trash_applicant_name VARCHAR(64),
+ trash_reason VARCHAR(255),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_org_id BIGINT,
+ skill_grade INTEGER,
+ service_grade INTEGER,
+ composite_grade NUMERIC(5,2),
+ sum_grade NUMERIC(10,2),
+ get_grade_times INTEGER,
+ grade_status INTEGER,
+ composite_grade_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.table_name IS '球台名称,如 “A17”“S1”,与 site_table_id 冗余,用于展示。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_name IS '助教姓名,如“何海婷”;与助教档案中的真实姓名一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_name IS '助教计费项目名称,如“2-佳怡”等,通常为展示用组合字段。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_group_name IS '助教项目所属的计费分组/套餐分组名称,目前导出数据中为空,未看到实际使用场景。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_count IS '台账计费时长(秒),通常与 real_use_seconds 接近或相等。取income_seconds TEXT';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.member_discount_amount IS '由会员卡折扣产生的优惠金额,当前样本中为 0,但字段语义明确。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.manual_discount_amount IS '收银员手动减免金额(人工改价);当前导出数据中为 0。 | 来源: manual_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_money IS '与助教结算的金额或服务成本金额,当前数据全部为 0,具体结算规则未见启用。 | 来源: service_money';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.returns_clock IS '退钟秒数(取消加钟或提前结束退回的时间),当前样本中全部为 0,未见业务使用。 | 来源: returns_clock';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_start_time IS '台账计费起始时间。 | 来源: ledger_start_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_end_time IS '台账计费结束时间,可作为本次服务结束时间。 | 来源: ledger_end_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_status IS '助教流水状态:当前数据为 1,表示正常有效;其他值预留给已作废、未结算等状态。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_confirm IS '确认状态:当前样本为 2,一般含义为 1=待确认,2=已确认/已完成(含义基于字段名和现有值推断)。 | 来源: is_confirm';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_single_order IS '是否单独订单:1 表示助教服务作为单独订单结算;0 表示与其他项目合单结算。当前样本全部为 1。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_not_responding IS '是否存在“未响应/爽约”等异常:0 表示正常;1 表示未响应或爽约(基于字段名推断,当前数据均为 0)。 | 来源: is_not_responding';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_trash IS '是否已废除:0 表示正常有效;1 表示已废除,与助教废除记录表(assistant_cancellation_records)对应。 | 来源: is_trash';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_id IS '提出废除申请的员工 ID,用于追溯谁发起了废除操作。 | 来源: trash_applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_name IS '废除申请人姓名,仅用于展示,与 trash_applicant_id 冗余。 | 来源: trash_applicant_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_reason IS '废除原因文案,如“顾客取消”“录入错误”,便于分析异常原因。 | 来源: trash_reason';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_user_id IS '营业员/销售员用户 ID,大多为 0,当前门店未明显使用此维度。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_name IS '营业员/销售员姓名,多数为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_org_id IS '营业员所属组织/部门 ID,多数为 0,尚未看到实际业务使用。 | 来源: salesman_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.skill_grade IS '课程技能评分(整数),当前样本全为 0,评价功能尚未启用。 | 来源: skill_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_grade IS '服务态度评分(整数),当前样本全为 0。 | 来源: service_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade IS '综合评分(技能+服务等加权结果),当前样本为 0。 | 来源: composite_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.sum_grade IS '累计评分总和,用于计算平均分,当前样本为 0。 | 来源: sum_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.get_grade_times IS '获得评价的次数,当前样本为 0。 | 来源: get_grade_times';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.grade_status IS '评价状态枚举:当前样本为 1,一般含义为“未评价/正常”,其他状态未见实际值。 | 来源: grade_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade_time IS '最近一次综合评分时间或评价更新时间,当前为默认时间 “0001-01-01 00:00:00”。 | 来源: composite_grade_time';
+
+-- dwd_assistant_trash_event
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
+ assistant_trash_event_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ assistant_no VARCHAR(32),
+ assistant_name VARCHAR(64),
+ charge_minutes_raw INTEGER,
+ abolish_amount NUMERIC(18,2),
+ trash_reason VARCHAR(255),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event.site_id IS '门店 ID。与其他 JSON 中的 siteId / site_id 含义一致。用来关联 dim_site。当前样例全部为同一门店(朗朗桌球),但设计上支持多门店。 | 来源: siteId | 角色: 外键(指向 dim_site)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_id IS '台桌 ID。对应 site_tables_master.json 中的 id。用于定位哪一张球台发生了助教废除,用于后续软关联台费流水、助教流水时的重要条件。 | 来源: tableId | 角色: 外键(指向 dim_table)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_area_id IS '台桌区域 ID。应与台桌维或区域维中的 area_id 一致,用于按区域统计(A 区/B 区/VIP 包厢等)。 | 来源: tableAreaId | 角色: 外键(潜在指向 dim_table_area)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_no IS '助教编号(工号/序号),如 ''2''、''4''、''27'' 等。与助教档案表 assistant_accounts_master.assistant_no、助教流水中的 assistantNo 一致,用于标识哪位助教。枚举:在门店内是有限编号集合,但并非硬编码含义。 | 来源: assistantOn | 角色: 外键(指向 dim_assistant)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_name IS '助教姓名/昵称,如 “泡芙”“佳怡”等。为冗余展示字段,真实姓名以助教档案为准。当前数据中与档案一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_trash_event.charge_minutes_raw IS '助教被废除前“已计费时长(分钟)”的原始值。单位为分钟。示例:214、3600、10800 等。0 表示尚未发生有效计费就被废除。当前数据中存在异常大值(例如 10800),这一业务含义需结合实际规则理解,但本字段原样保留。枚举:数值型,无固定枚举。 | 来源: pdChargeMinutes';
+COMMENT ON COLUMN dwd_assistant_trash_event.abolish_amount IS '与本次助教废除操作关联的金额,单位元。字面含义为“助教废除金额”。当前样例均为非负数,如 5.83、570.00、0.00 等。正负方向:按照 ODS/JSON 原样保留,暂不在数仓层赋予“收入/支出”的方向含义,后续在 DWS 层按业务规则解释(例如是退还顾客、扣除收益等)。 | 来源: assistantAbolishAmount';
+COMMENT ON COLUMN dwd_assistant_trash_event.trash_reason IS '废除原因的文本说明,例如可以写“顾客临时取消”“误操作”等。当前样例中全部为空字符串,说明前台并未使用该字段。但从结构上看,是一个自由文本字段,不是枚举。 | 来源: trashReason';
+COMMENT ON COLUMN dwd_assistant_trash_event.create_time IS '这条废除记录创建的时间,格式 YYYY-MM-DD HH:MM:SS。代表系统正式记录“废除操作”的时刻,用于和助教服务流水按时间窗口做软关联(结合 site、table、assistant 等条件)。 | 来源: createTime';
+
+-- dwd_assistant_trash_event_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event_Ex (
+ assistant_trash_event_id BIGINT,
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_name IS '台桌名称/编号,便于直观看报表,如 “C1”“B9”“VIP1”等。文案冗余自台桌维度。枚举:在门店范围内是有限集合,但不是固定编码表。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_area_name IS '台桌区域名称(中文),如 “A区”“B区”“C区”“VIP包厢”“补时长”等。展示用文本,具体层级信息由区域维表提供。 | 来源: tableArea';
+
+-- dwd_member_balance_change
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
+ balance_change_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ card_type_id BIGINT,
+ card_type_name VARCHAR(32),
+ member_name VARCHAR(64),
+ member_mobile VARCHAR(20),
+ balance_before NUMERIC(18,2),
+ change_amount NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ from_type INTEGER,
+ payment_method INTEGER,
+ change_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ remark VARCHAR(255),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_id IS '租户/品牌 ID,在整体系统中唯一标识一家商户。当前样本中为同一值。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.site_id IS '本次余额变动发生的门店 ID。通常对应具体门店;样本中:非 0 为“朗朗桌球”,0 代表平台级/虚拟门店场景(如活动抵用券结算)。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.register_site_id IS '办卡门店 ID(卡注册门店)。与 site_id 区分:register_site_id=当初办卡门店,site_id=本次余额变动实际发生门店。当前样本中全部相同。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_id IS '租户维度会员 ID(同一租户内的会员主键),用于关联会员档案。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.system_member_id IS '系统全局会员 ID(跨租户统一的会员标识)。当前只有一个门店,但结构上允许同一人跨租户共享该 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_card_id IS '会员卡账户 ID(租户内唯一的一张具体卡,例如某人的储值卡/酒水卡/台费卡/活动抵用券等)。本次余额变动作用于这张卡。 | 来源: tenant_member_card_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_id IS '卡种类型 ID。与 card_type_name 一一对应,用于区分不同卡种(储值卡/活动抵用券/酒水卡/台费卡)。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_name IS '卡种名称(中文):• 储值卡:通用储值卡;• 活动抵用券:活动送券型卡;• 酒水卡:指定用于酒水类消费;• 台费卡:指定用于台费消费。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_member_balance_change.member_name IS '会员姓名/称呼(如“曾丹烨”“葛先生”“胡先生”),主要用于运营、客服和人工识别。 | 来源: memberName';
+COMMENT ON COLUMN dwd_member_balance_change.member_mobile IS '会员手机号(完整号码字符串),是会员识别、营销触达的重要字段。 | 来源: memberMobile';
+COMMENT ON COLUMN dwd_member_balance_change.balance_before IS '本次变动前的卡内余额,单位:元。可为 0、数百、数千等。 | 来源: before';
+COMMENT ON COLUMN dwd_member_balance_change.change_amount IS '本次余额变动金额,单位:元:• 正数:余额增加(充值、赠送、调整加款等);• 负数:余额减少(消费扣款、退款冲减、活动抵扣等)。所有记录严格满足:balance_after = balance_before + change_amount(浮点精度内)。 | 来源: account_data';
+COMMENT ON COLUMN dwd_member_balance_change.balance_after IS '本次变动后的卡内余额,单位:元。由 before + account_data 计算而得,在源数据中已给出。 | 来源: after';
+COMMENT ON COLUMN dwd_member_balance_change.from_type IS '余额变动来源类型枚举(控制业务含义与方向):• 1:日常消费扣款 —— change_amount 为负数,payment_method=0,表示用卡支付消费被扣余额;• 3:充值增加 —— change_amount 为正数,payment_method=4,表示顾客通过外部支付为卡充值(扫码、银行卡等);• 4:调整/赠送增加 —— change_amount 为正数,payment_method=3,通常为后台赠送或手工加款;• 7:充值退款 —— change_amount 为负数,remark=''充值退款'',表示对历史充值做退款,以减少卡内余额方式体现;• 9:活动抵用券相关余额冲减 —— change_amount 为负数,卡种为“活动抵用券”,site_id=0,表示活动券额度被扣回或结算;• 2:其他增加 —— 当前仅 1 条正数样本(+1865.80),具体业务类型不明,但可确定为余额增加类。总体上:1/7/9 为减余额类,2/3/4 为加余额类。 | 来源: from_type';
+COMMENT ON COLUMN dwd_member_balance_change.payment_method IS '支付/变动渠道枚举(与源系统支付方式枚举一致):• 0:内部结算/无外部支付 —— 日常消费扣款、内部扣减、退款冲减等场景,新资金流不在本记录中产生;• 3:赠送/后台调整渠道 —— 与 from_type=4 搭配出现,表示此余额增加不是顾客付钱,而是后台发放或内部调账;• 4:充值外部支付渠道 —— 与 from_type=3 搭配出现,代表顾客通过某外部渠道完成充值(具体是微信/支付宝/银行卡等需要结合支付枚举表进一步映射)。 | 来源: payment_method';
+COMMENT ON COLUMN dwd_member_balance_change.change_time IS '余额变动时间(记录创建时间),格式 YYYY-MM-DD HH:MM:SS。通常紧邻实际交易发生时间,用于按时间线分析资金变动。 | 来源: create_time';
+COMMENT ON COLUMN dwd_member_balance_change.is_delete IS '逻辑删除标记:• 0:正常记录(当前样本全部为 0);• 1:逻辑删除(标记为删除但数据库保留,用于追溯)。分析时通常需要过滤掉 is_delete=1 的记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_member_balance_change.remark IS '余额变动备注信息。当前样本中主要为:• 空字符串:无额外说明;• 充值退款:明确标记该条记录为“充值退款”业务,与 from_type=7 完全对应。后续可能出现其他业务备注。 | 来源: remark';
+
+-- dwd_member_balance_change_EX
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
+ balance_change_id BIGINT,
+ pay_site_name VARCHAR(64),
+ register_site_name VARCHAR(64),
+ refund_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change_EX.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.pay_site_name IS '余额变动发生门店名称,对应 site_id 的中文名。示例:朗朗桌球;当 site_id = 0 时通常为空字符串。纯展示冗余。 | 来源: paySiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.register_site_name IS '办卡门店名称,对应 register_site_id 的中文名。当前样本全部为 朗朗桌球,属于冗余展示。 | 来源: registerSiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.refund_amount IS '退款金额字段。在当前样本数据中全部为 0.00,推测用于区分“退回卡内余额”和“原路退回”等更细的退款模式,但目前未启用。 | 来源: refund_amount';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_id IS '操作员 ID,执行本次余额变动操作的员工账号主键。可关联员工/账号维度。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_name IS '操作员名称及职位说明,例如:收银员:郑丽珊、店长:谢晓洪 等,是对 operator_id 的可读冗余。 | 来源: operator_name';
+
+-- dwd_groupbuy_redemption
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
+ redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_charge_seconds INTEGER,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_coupon_id BIGINT,
+ coupon_origin_id BIGINT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ order_coupon_channel INTEGER,
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ promotion_seconds INTEGER,
+ coupon_code VARCHAR(64),
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ ledger_name VARCHAR(128),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_id IS '租户/品牌 ID。与其他表统一的租户标识,用于品牌维度聚合。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.site_id IS '门店 ID。与门店维度及其他业务事实中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_id IS '球台 ID。与台桌维度表中的 id 对应,用于确定具体哪一张球台。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_table_area_id IS '租户级台区组合 ID。与团购套餐定义中的 tenant_table_area_id_list 元素对应,表示该券实际使用时所在的台区组合。用于校验券的适用台区是否匹配实际台桌。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_charge_seconds IS '本次结算中该球台总计计费的秒数(整台计费时间)。当台上除了券覆盖时长之外还有额外计费时间时,该值会大于券核销时长。 | 来源: table_charge_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_trade_no IS '订单交易号。与台费流水、商品销售、助教服务、小票详情等表的 order_trade_no 一致,用于将同一笔结账中的所有明细串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_settle_id IS '结算单 ID。与结账记录和小票详情中的结算主键对应,用于从团购券核销记录跳转到整单结算。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_id IS '订单中的“券使用记录 ID”。与平台或内部券核销表中的主键一致,用于在订单内部定位这条券使用记录。当前与 coupon_origin_id 数值相等。 | 来源: order_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_origin_id IS '上游系统或第三方平台中该券记录的主键 ID。可在平台验券记录中查到券的来源平台、原订单等。当前与 order_coupon_id 数值一致,但语义是“券来源 ID”。 | 来源: coupon_origin_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_activity_id IS '促销活动 ID。每条记录对应一个活动主键,用于识别券所属的促销活动或团购活动。 | 来源: promotion_activity_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_coupon_id IS '团购套餐定义 ID。与 group_buy_packages.json 中的 id 一一对应,表示当前使用的是哪一种团购套餐(例如某款“一小时套餐”“两小时套餐”)。 | 来源: promotion_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_channel IS '券渠道类型枚举。观测值:1(大量记录)、2(少量记录)。用于区分券的来源渠道,例如不同团购平台或内部券。具体数值与渠道名称的映射由业务配置决定。 | 来源: order_coupon_channel | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_unit_price IS '本次券在台费侧对应的标准单价,单位元/小时。典型值如 29.9、39.9、59.9、69.9 等。与门店台费计费规则中的单价相对应,用于计算券对应的金额。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_count IS '本次券实际核销的计费秒数。大部分记录等于 promotion_seconds,少数略小于标准时长,表示这张券只覆盖了本次台费的一部分时长。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_amount IS '本次团购券实际冲抵台费的金额。大部分记录中该值与 coupon_money 相等,少数存在小数差异,来源于按单价与秒数换算的结果。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_money IS '本次核销时,团购券在门店侧对应的金额额度(可抵扣金额)。同一种 promotion_coupon_id 下,该值固定,例如某套餐固定为 48.00 元、某套餐固定为 96.00 元等。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_seconds IS '团购套餐定义的标准时长权益,单位秒。观测枚举值为 3600、7200、14400,分别对应 1 小时、2 小时、4 小时。与团购套餐定义表中的 duration 字段一致。 | 来源: promotion_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_code IS '团购券券码字符串。每条记录一个唯一券码,例如“0107892475999”。用于与平台验券记录、券购买记录等做一一对应,追踪券的全生命周期。 | 来源: coupon_code | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_single_order IS '是否作为单独订单行。观测值:1 为主,表示以独立条目方式结算;0 为个别记录,表示嵌入某种组合结算结构。具体业务含义依赖上层订单结构设计。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_delete IS '逻辑删除标记。0 表示正常记录,1 表示逻辑删除但数据仍保留用于追溯。当前样本全部为 0,用于过滤有效记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_name IS '团购项目记账名称,如“全天A区中八一小时”“B区桌球一小时”“中八、斯诺克包厢两小时”等。通常与团购套餐名称相近,用于报表展示和套餐维度分析。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption.create_time IS '本条团购券核销流水的创建时间,通常即核销时间,格式为“YYYY-MM-DD HH:MM:SS”。用于时间维度分析和数据分区。 | 来源: create_time';
+
+-- dwd_groupbuy_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
+ redemption_id BIGINT,
+ site_name VARCHAR(64),
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ order_pay_id BIGINT,
+ goods_option_price NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ offer_type INTEGER,
+ ledger_status INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ ledger_group_name VARCHAR(128),
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.site_name IS '门店名称。当前样本全部为同一门店,仅作冗余展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_name IS '球台名称或台号。如 A7、A11、B1 等。用于业务报表展示与人工识别。 | 来源: tableName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_area_name IS '台区名称。观测枚举值包括 A区、B区、斯诺克区、麻将房。实际取值随门店台区配置变化。 | 来源: tableAreaName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.order_pay_id IS '支付流水 ID。部分记录为 0,表示未在当前导出范围内关联到具体支付记录。真实含义为“指向支付记录表中的支付流水”。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_option_price IS '商品规格价格,用于商品类促销分摊时使用。当前在团购券核销场景中全部为 0,仅作为结构预留。 | 来源: goodsOptionPrice';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_promotion_money IS '本次券使用中分摊到“商品”部分的促销金额。当前所有记录为 0,说明本门店的团购券未用于商品抵扣。 | 来源: goods_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_service_promotion_money IS '本次券使用中分摊到“台费服务费”部分的促销金额。当前样本全部为 0,结构上用于支持更细粒度的费用拆分。 | 来源: table_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_promotion_money IS '本次券使用中分摊到“助教服务”的促销金额。当前全部为 0,说明团购券尚未用于助教服务的抵扣。 | 来源: assistant_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_service_promotion_money IS '进一步细分助教服务对应的促销金额。当前为 0,仅预留结构以支持复杂场景。 | 来源: assistant_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.reward_promotion_money IS '本次促销中属于“奖励金、积分”等来源的促销金额分摊。当前为 0,预留用于积分或奖励金同时参与活动时的金额拆分。 | 来源: reward_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.recharge_promotion_money IS '来自“充值赠送”等储值优惠的促销金额分摊。当前为 0,预留用于将来区分“券优惠”和“充值赠送优惠”的场景。 | 来源: recharge_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.offer_type IS '优惠类型枚举。当前样本值全部为 1,表示本门店使用的团购券均为同一类型(例如“套餐券”)。其他取值可能对应满减、折扣、代金券等优惠类型,在本数据中未出现。 | 来源: offer_type';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_status IS '流水状态。观测值全部为 1。常规含义为:1 表示正常有效记录;其他值预留用于表示作废、撤销、未生效等状态。当前导出仅包含正常状态记录。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_id IS '执行本次券核销操作的操作员 ID。可与员工维度表对接,用于分析不同操作员的核销行为与绩效。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_name IS '操作员名称及角色说明,例如“收银员:郑丽珊”。与 operator_id 冗余,对报表展示友好,但不参与模型关联。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_user_id IS '营业员用户 ID。当前全部为 0,表示本门店在团购券场景未单独记录营业员信息。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_name IS '营业员姓名。当前为空字符串。结构上用于记录拉单或促销的业务员信息。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_role_id IS '营业员角色 ID。当前为 0,预留用于标识营业员在组织中的角色类型。 | 来源: salesman_role_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_org_id IS '营业员所属组织 ID。来源字段为 sales_man_org_id,DWD 层统一命名为 salesman_org_id。当前为 0,用于将来对接组织架构维度。 | 来源: sales_man_org_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_group_name IS '团购项目的记账分组名称。当前全部为空,预留给将来按团购项目大类分组(例如“团购台费”“团购包厢”)使用。 | 来源: ledger_group_name';
+
+-- dwd_platform_coupon_redemption
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
+ platform_coupon_redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ coupon_code VARCHAR(64),
+ coupon_channel INTEGER,
+ coupon_name VARCHAR(200),
+ sale_price NUMERIC(10,2),
+ coupon_money NUMERIC(10,2),
+ coupon_free_time INTEGER,
+ channel_deal_id BIGINT,
+ deal_id BIGINT,
+ group_package_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ certificate_id VARCHAR(64),
+ verify_id VARCHAR(64),
+ use_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ consume_time TIMESTAMPTZ,
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.tenant_id IS '租户 ID,品牌级别标识。例如整套系统中的“朗朗桌球”品牌。与其他表的 tenant_id 一致,用于划分租户数据域。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于区分不同门店。siteProfile.id 与此字段相同,本表不再冗余门店快照。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_code IS '第三方团购券券码,顾客出示的核销码。当前样本中全表唯一,可视为业务自然主键,用于验券、对账、查询。 | 来源: coupon_code';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_channel IS '券来源渠道枚举,表示第三方平台渠道编号。观测值:1,2。具体含义需结合系统配置,一般可理解为:1 表示平台渠道 1(主平台),2 表示平台渠道 2(其他入口或子平台)。 | 来源: coupon_channel';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_name IS '第三方团购券产品名称,例如“【全天可用】中八桌球一小时(A区)”“1小时中八台球【11月特惠】(A区)”等。用于报表展示和区分不同团购产品。 | 来源: coupon_name';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.sale_price IS '顾客在第三方平台实际支付的团购售价,例如 11.11、29.90、39.90 等。始终小于 coupon_money,体现“折后价”。 | 来源: sale_price';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_money IS '券面值或套餐价值,即系统认为该券可抵扣的金额,例如 48.00、58.00、68.00、96.00、116.00、288.00。与 coupon_name 有固定对应关系。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_free_time IS '券附带的赠送时长,单位:秒。当前样本全部为 0,表示无独立赠送时长。若未来有赠送时间型券,则该字段存储赠送的秒数。 | 来源: coupon_free_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.channel_deal_id IS '渠道侧团购商品 ID(第三方平台 dealId)。值域有限(约 9 个值),与 coupon_name 一一对应。用于对接第三方接口和按平台商品维度统计。 | 来源: channel_deal_id | 角色: - 或 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.deal_id IS '平台/系统侧团购商品 ID。多数记录为非 0 整数,也有部分为 0。与 coupon_name 存在稳定对应关系,0 表示内部未配置或未同步。未来可作为内部团购商品维度外键。 | 来源: deal_id | 角色: 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.group_package_id IS '内部“团购套餐”定义表主键 ID。当前样本中全部为 0,表示平台券尚未映射到自有团购套餐;从设计上是预留的外键字段。 | 来源: group_package_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_order_id IS '门店内部订单 ID。本次平台券核销所挂靠的店内订单号。用于与结账记录、台费流水、商品销售等事实表通过订单维度关联。 | 来源: site_order_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.table_id IS '使用团购券的球台 ID。与 dim_site_table.table_id 对应,用于统计每张球台的第三方平台引流情况。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.certificate_id IS '第三方平台侧券实例 ID(凭证 ID),通常为 16–19 位数字字符串。用于与外部平台对账与查询核销结果。存在重复值,不能单独作为唯一键。 | 来源: certificate_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.verify_id IS '第三方平台核销记录 ID。大部分记录为空,少量有值。存在时可用于精确反查平台侧核销记录。 | 来源: verify_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.use_status IS '券使用状态枚举。观测值:1、2。1 表示已使用/已核销(正常消耗);2 表示已退款/已撤销或使用后反冲的状态。是判断券生命周期状态的核心字段。 | 来源: use_status';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.is_delete IS '逻辑删除标志。0 表示未删除;1 表示已逻辑删除。与 use_status 独立:即便业务状态异常(如 use_status=2),也可能 is_delete 仍为 0 以保留记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.create_time IS '系统记录创建时间,即核销记录写入本系统的时间。格式为 YYYY-MM-DD HH:MM:SS。通常与 consume_time 相差约 1 秒。 | 来源: create_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.consume_time IS '券被核销/使用的业务时间,代表实际团购券使用发生的时间点。后续按核销日期统计核销量时以该字段为准。 | 来源: consume_time';
+
+-- dwd_platform_coupon_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
+ platform_coupon_redemption_id BIGINT,
+ coupon_cover VARCHAR(255),
+ coupon_remark VARCHAR(255),
+ groupon_type INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(50),
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_cover IS '券封面图片地址 URL,用于前端展示团购券图片。对经营分析和结算逻辑无影响。 | 来源: coupon_cover';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_remark IS '券描述或备注信息,用于展示券规则、说明文字。未参与计算和关联逻辑。 | 来源: coupon_remark';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.groupon_type IS '团购券类型枚举。当前样本全部为 1。推断含义:1 表示标准团购券,其他值预留为次卡、套餐券、权益券等类型。 | 来源: groupon_type';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_id IS '执行验券操作的员工/收银员账号 ID。当前样本中多数为同一值。可与员工/账号维度表关联。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_name IS '操作员姓名或显示名,例如“收银员:郑丽珊”。是 operator_id 的冗余展示字段,用于报表展示。 | 来源: operator_name';
+
+-- dwd_recharge_order
+CREATE TABLE IF NOT EXISTS dwd_recharge_order (
+ recharge_order_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ member_id BIGINT,
+ member_name_snapshot TEXT,
+ member_phone_snapshot TEXT,
+ tenant_member_card_id BIGINT,
+ member_card_type_name TEXT,
+ settle_relate_id BIGINT,
+ settle_type INTEGER,
+ settle_name TEXT,
+ is_first INTEGER,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ payment_method INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order.tenant_id IS '租户/品牌 ID;与其他 JSON 中 tenantId 含义一致。 | 来源: tenantId | 角色: 外键(dim_tenant)';
+COMMENT ON COLUMN dwd_recharge_order.site_id IS '门店 ID;与 siteProfile.id 一致,用于关联门店维度。 | 来源: siteId | 角色: 外键(dim_site)';
+COMMENT ON COLUMN dwd_recharge_order.member_id IS '会员 ID;对应会员档案中的 tenantMemberInfos.id。标识给哪个会员充值。 | 来源: memberId | 角色: 外键(dim_member)';
+COMMENT ON COLUMN dwd_recharge_order.member_name_snapshot IS '会员姓名/昵称快照,可能是名称或手机号字符串。 | 来源: memberName';
+COMMENT ON COLUMN dwd_recharge_order.member_phone_snapshot IS '会员手机号快照。 | 来源: memberPhone';
+COMMENT ON COLUMN dwd_recharge_order.tenant_member_card_id IS '会员卡实例 ID(某张具体卡);可关联 dim_member_card_account。 | 来源: tenantMemberCardId | 角色: 外键(dim_member_card_account)';
+COMMENT ON COLUMN dwd_recharge_order.member_card_type_name IS '会员卡类型名称;当前样例主要有:“储值卡”、“月卡”。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_recharge_order.settle_relate_id IS '结算关联 ID;用于与支付记录等跨表关联(类似业务单 ID)。 | 来源: settleRelateId | 角色: 外键(与支付/结算域软关联)';
+COMMENT ON COLUMN dwd_recharge_order.settle_type IS '结算类型枚举:5=“充值订单”(正常充值);7=“充值撤销”(冲销记录)。 | 来源: settleType';
+COMMENT ON COLUMN dwd_recharge_order.settle_name IS '结算类型名称:"充值订单"、"充值撤销";前端展示用。 | 来源: settleName';
+COMMENT ON COLUMN dwd_recharge_order.is_first IS '是否首充标记。取值:1 或 2。理论含义类似“是否首充”,但 1/2 的精确定义需系统字典确认。 | 来源: isFirst';
+COMMENT ON COLUMN dwd_recharge_order.pay_amount IS '本条记录的充值金额(可为正/负):正数=实际充值金额;负数=撤销流水金额(settleType=7)。 | 来源: payAmount';
+COMMENT ON COLUMN dwd_recharge_order.refund_amount IS '对该充值订单的退款金额(通常为正数);原始充值单上为已退款金额,对应会有一条负数的“充值撤销”记录。 | 来源: refundAmount';
+COMMENT ON COLUMN dwd_recharge_order.point_amount IS '计入会员账户的储值/积分金额;多数情况下等于 pay_amount 的绝对值;撤销记录一般为 0。 | 来源: pointAmount';
+COMMENT ON COLUMN dwd_recharge_order.cash_amount IS '现金收款金额;样本中少数为 3000/5000,其余为 0。 | 来源: cashAmount';
+COMMENT ON COLUMN dwd_recharge_order.payment_method IS '支付方式编码。样本取值:1、2、4;具体对应渠道(现金/微信/支付宝/银行卡等)需系统“支付方式字典”确认。 | 来源: paymentMethod';
+COMMENT ON COLUMN dwd_recharge_order.create_time IS '充值记录创建时间(收银完成时间);用于时间分区、统计。 | 来源: createTime';
+COMMENT ON COLUMN dwd_recharge_order.pay_time IS '支付完成时间;通常与 create_time 接近或相同。 | 来源: payTime';
+
+-- dwd_recharge_order_Ex
+CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
+ recharge_order_id BIGINT,
+ site_name_snapshot TEXT,
+ settle_status INTEGER,
+ is_bind_member BOOLEAN,
+ is_activity BOOLEAN,
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ can_be_revoked BOOLEAN,
+ online_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name_snapshot TEXT,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ order_remark TEXT,
+ table_id INTEGER,
+ serial_number INTEGER,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order_Ex.site_name_snapshot IS '门店名称快照,如“朗朗桌球”;仅用于展示,门店改名后本字段不变。 | 来源: siteName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.settle_status IS '结算状态;当前数据全部为 2,推测 2=已完成。其它状态未出现在样本中。 | 来源: settleStatus';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_bind_member IS '是否绑定为会员/其他绑定标记;当前所有记录为 False,而又都有 memberId,实际业务含义不清。 | 来源: isBindMember';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_activity IS '是否关联营销活动;当前全部为 False,表示样本周期内充值未绑定活动。 | 来源: isActivity';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_coupon IS '本次充值是否使用优惠券;当前样本全部为 False。结构上预留“充值用券”的能力。 | 来源: isUseCoupon';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_discount IS '是否使用折扣(如充值折扣);样本中全为 False。 | 来源: isUseDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.can_be_revoked IS '当前记录是否仍可撤销;样本中全为 False(导出时均不可撤销)。 | 来源: canBeRevoked';
+COMMENT ON COLUMN dwd_recharge_order_Ex.online_amount IS '线上支付金额(如微信、支付宝等);当前样本为 0,但字段为支付渠道拆分预留。 | 来源: onlineAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.balance_amount IS '从账户余额中支付的金额;充值场景通常为 0(用余额充值没有实际意义)。 | 来源: balanceAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.card_amount IS '从其他储值卡或某种卡余额支付的金额;当前样本全为 0。 | 来源: cardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_amount IS '使用券直接支付的金额(如储值券);当前样本为 0。 | 来源: couponAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_card_amount IS '充值到卡上的金额(与 point_amount 区分不同资金属性);样本为 0,结构预留。 | 来源: rechargeCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.gift_card_amount IS '赠送卡金额(如买 1000 送 100 的赠送部分);当前样本为 0。 | 来源: giftCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.prepay_money IS '预付款金额(订金);当前样本为 0,充值未启用此场景。 | 来源: prepayMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.consume_money IS '消费总金额;在充值文件中全部为 0,实际用于消费场景(台费/商品)的结算模型复用字段。 | 来源: consumeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_money IS '商品消费金额(充值记录中为 0)。 | 来源: goodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.real_goods_money IS '实际应计商品金额(扣除折扣后);充值记录中为 0。 | 来源: realGoodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_charge_money IS '台费金额;充值记录中为 0,来自通用结算模型。 | 来源: tableChargeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.service_money IS '服务项目金额(如助教、其他服务);充值中为 0。 | 来源: serviceMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.activity_discount IS '营销活动折扣金额;当前样本为 0。 | 来源: activityDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.all_coupon_discount IS '各类优惠券、团购券综合折扣金额;样本为 0。 | 来源: allCouponDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_promotion_money IS '商品促销优惠金额;样本为 0。 | 来源: goodsPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_promotion_money IS '助教相关促销优惠金额;样本为 0。 | 来源: assistantPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_pd_money IS '助教配单金额/相关费用;样本为 0。 | 来源: assistantPdMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_cx_money IS '助教冲销/促销相关金额;样本为 0。 | 来源: assistantCxMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_manual_discount IS '助教手工减免金额;样本为 0。 | 来源: assistantManualDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_sale_amount IS '券/套餐销售金额(售卖券时使用);充值场景中为 0。 | 来源: couponSaleAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.member_discount_amount IS '因会员折扣产生的优惠金额;在充值样本中为 0。 | 来源: memberDiscountAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_price IS '积分抵扣产生的价差(价格部分);样本为 0。 | 来源: pointDiscountPrice';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_cost IS '积分抵扣对应的成本金额;样本为 0。 | 来源: pointDiscountCost';
+COMMENT ON COLUMN dwd_recharge_order_Ex.adjust_amount IS '手工调整金额(非抹零);样本为 0。 | 来源: adjustAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.rounding_amount IS '抹零金额(四舍五入产生的差额);样本为 0。 | 来源: roundingAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_id IS '操作该笔充值的收银员/员工 ID。 | 来源: operatorId | 角色: 外键(将来可关联 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_name_snapshot IS '操作员姓名快照,便于直接阅读;与 operator_id 对应。 | 来源: operatorName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_user_id IS '营业员用户 ID;当前样本全部为 0。 | 来源: salesManUserId | 角色: 外键(潜在 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_name IS '营业员/销售员姓名;样本为空字符串。 | 来源: salesManName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.order_remark IS '充值订单备注,如手工说明;当前样本为空。 | 来源: orderRemark';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_id IS '台桌 ID;充值场景下全部是 0,表示该订单不挂具体球台。 | 来源: tableId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.serial_number IS '流水/小票序号;当前样本全部为 0,本门店未启用。 | 来源: serialNumber';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_id IS '撤销相关订单 ID(被撤销原单或撤销单指针);样本中存在值但逻辑未完全启用。 | 来源: revokeOrderId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_name IS '撤销单名称/说明;样本全为空。 | 来源: revokeOrderName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_time IS '撤销时间;当前样本为空,撤销信息主要通过负数流水与 refund_amount 表达。 | 来源: revokeTime';
+
+-- dwd_payment
+CREATE TABLE IF NOT EXISTS dwd_payment (
+ payment_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ payment_method INTEGER,
+ online_pay_channel INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ pay_date DATE,
+ PRIMARY KEY (payment_id)
+);
+COMMENT ON COLUMN dwd_payment.payment_id IS '支付流水主键ID。与源系统 id 一致。每条支付流水唯一标识一条支付行为(包括金额为 0 的记录)。 | 来源: payment_transactions.id | 角色: 主键';
+COMMENT ON COLUMN dwd_payment.site_id IS '门店ID。当前样本中全部为同一门店 2790685415443269。在数仓中外键关联 dim_site.site_id。 | 来源: payment_transactions.site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_payment.relate_type IS '业务关联类型枚举,用来区分这条支付流水对应哪一类业务单据:• 2:结账单支付,对应结账记录 settlement_records 中的结账单;• 5:会员卡充值/账户变动类支付,对应会员余额/充值业务单号,在会员余额变更或充值结算中复用;• 1:其他业务类型,目前样本中仅有 1 条记录,具体业务含义待业务侧补充。 | 来源: payment_transactions.relate_type | 角色: −';
+COMMENT ON COLUMN dwd_payment.relate_id IS '关联业务记录ID,配合 relate_type 使用,是一个“多态外键”:• 当 relate_type = 2 时:relate_id = settlement_records.settleList.id(结账记录主键,对应 dwd_settlement_head_di.order_settle_id);• 当 relate_type = 5 时:relate_id = 会员卡余额变动/充值业务单号,在会员余额变更流水中同名字段使用;• 当 relate_type = 1 时:关联具体业务尚未确认,仅可视为预留类型。 | 来源: payment_transactions.relate_id | 角色: 外键(多业务类型)';
+COMMENT ON COLUMN dwd_payment.pay_amount IS '本次支付金额,单位元。为收入类字段,当前样本全部为非负数:• 正数:实际通过该支付方式收取的金额;• 0:仍生成支付流水,但实收金额为 0(例如整单由会员优惠、团购券、余额等抵扣),当前样本中有 140 条记录金额为 0。 | 来源: payment_transactions.pay_amount | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_status IS '支付状态枚举。当前样本中仅出现:• 2:支付成功。其它可能的状态(未支付、支付中、失败、已退款等)在本次导出中未出现,需以后按系统支付状态配置补充。由于本 JSON 仅导出成功记录,可以视作“成功支付流水视图”。 | 来源: payment_transactions.pay_status | 角色: −';
+COMMENT ON COLUMN dwd_payment.payment_method IS '支付方式枚举。当前样本中出现的取值:• 2:共 140 条记录;• 4:共 60 条记录。具体取值与“支付方式配置表”对应,例如可能代表现金、扫码支付、银行卡等。由于配置表未导出,在数仓中应作为枚举码字段,通过后续 dim_payment_method 进行解码。不要在数仓层擅自写死“2=微信、4=支付宝”等含义。 | 来源: payment_transactions.payment_method | 角色: 外键(预期关联支付方式维度)';
+COMMENT ON COLUMN dwd_payment.online_pay_channel IS '线上支付通道枚举。用于进一步细分线上渠道,例如:• 0:无线上通道/线下,或未区分具体线上通道(当前样本全部为 0);• 1:微信(推测,未在样本中出现);• 2:支付宝(推测,未在样本中出现)。目前门店在当前时间段内尚未使用该字段进行实际区分,业务含义需结合正式配置确认。 | 来源: payment_transactions.online_pay_channel | 角色: −';
+COMMENT ON COLUMN dwd_payment.create_time IS '支付流水创建时间,格式 YYYY-MM-DD HH:MM:SS。通常是发起支付请求的时间。当前样本中 create_time 与 pay_time 多数相同,但模型上允许两者不同(例如异步支付)。 | 来源: payment_transactions.create_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_time IS '支付完成时间(支付成功时间戳),格式 YYYY-MM-DD HH:MM:SS。用于统计资金实际入账时间,以及与结账时间进行对齐分析。 | 来源: payment_transactions.pay_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_time 截取 YYYY-MM-DD 得到。例如 pay_time = ''2025-11-09 23:35:57'' 时,pay_date = ''2025-11-09''。用于 DWD 表按天分区和日粒度汇总。 | 来源: 由 payment_transactions.pay_time 派生 | 角色: −';
+
+-- dwd_refund
+ CREATE TABLE IF NOT EXISTS dwd_refund (
+ refund_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ channel_fee NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ payment_method INTEGER,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型) | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund.tenant_id IS '租户/品牌 ID,标识所属商户。与其他表中的 tenant_id 一致。 | 来源: tenant_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于分门店分析。 | 来源: site_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.relate_type IS '业务类型枚举,指示本退款对应哪类业务主单:当前样本值 {2, 5}:2=消费/结账类业务;5=充值/储值类业务(具体定义以业务字典为准)。与 relate_id 组合使用。 | 来源: relate_type';
+ COMMENT ON COLUMN dwd_refund.relate_id IS '关联的业务主键 ID,含义依赖 relate_type:relate_type=2 时通常指结账主单 ID;relate_type=5 时通常指充值/储值业务单 ID。同一个 relate_id 可能有多笔退款(分批退款)。 | 来源: relate_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.pay_amount IS '本次退款的资金金额,统一为负数。绝对值即退款金额,例如 -5000.00 表示退款 5000 元。 | 来源: pay_amount';
+ COMMENT ON COLUMN dwd_refund.channel_fee IS '第三方支付渠道对本次退款收取的手续费。当前样本为 0.00,用于通道成本核算。 | 来源: channel_fee';
+ COMMENT ON COLUMN dwd_refund.pay_time IS '退款在支付渠道/系统中发生的时间(退款完成时间),用于对账及按时间统计。 | 来源: pay_time';
+ COMMENT ON COLUMN dwd_refund.create_time IS '本条退款流水在系统内创建时间,用于区分记录生成时间与渠道时间。 | 来源: create_time';
+ COMMENT ON COLUMN dwd_refund.payment_method IS '支付方式枚举,指本次退款对应的原支付方式(如通道)。样本出现值 4,支付记录中有 {2,4},具体含义需参照支付方式配置表。 | 来源: payment_method';
+ COMMENT ON COLUMN dwd_refund.member_id IS '关联的会员 ID,对应会员档案表主键。样本为 0,表示未绑定会员。 | 来源: member_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.member_card_id IS '关联的会员卡账户 ID,对应会员卡账户/储值卡维度主键。样本为 0,当前没有“退到会员卡”的记录。 | 来源: member_card_id | 角色: 外键';
+
+
+ CREATE TABLE IF NOT EXISTS dwd_refund_Ex (
+ refund_id BIGINT,
+ tenant_name VARCHAR(64),
+ pay_sn BIGINT,
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ action_type INTEGER,
+ is_revoke INTEGER,
+ is_delete INTEGER,
+ check_status INTEGER,
+ online_pay_channel INTEGER,
+ online_pay_type INTEGER,
+ pay_terminal INTEGER,
+ pay_config_id INTEGER,
+ cashier_point_id INTEGER,
+ operator_id BIGINT,
+ channel_payer_id VARCHAR(128),
+ channel_pay_no VARCHAR(128),
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund_Ex.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。 | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund_Ex.tenant_name IS '租户名称,例如“朗朗桌球”。与租户维度中的名称冗余。 | 来源: tenantName';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_sn IS '支付流水内部序号。退款记录中样本全部为 0,未看到实际使用场景,含义未说明。 | 来源: pay_sn';
+ COMMENT ON COLUMN dwd_refund_Ex.refund_amount IS '本次退款金额(正数)设计字段,样本为 0.00,实际使用 pay_amount。 | 来源: refund_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.round_amount IS '退款过程中的舍入/抹零金额。 | 来源: round_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.balance_frozen_amount IS '与会员余额相关的冻结金额,样本为 0。 | 来源: balance_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.card_frozen_amount IS '与某张会员卡余额相关的冻结金额,样本为 0。 | 来源: card_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_status IS '退款状态枚举。样本中全部为 2(成功/已完成)。 | 来源: pay_status';
+ COMMENT ON COLUMN dwd_refund_Ex.action_type IS '资金动作类型枚举。样本全部为 2(退款)。 | 来源: action_type';
+ COMMENT ON COLUMN dwd_refund_Ex.is_revoke IS '是否为撤销型退款:0=正常退款;1=撤销原支付。 | 来源: is_revoke';
+ COMMENT ON COLUMN dwd_refund_Ex.is_delete IS '逻辑删除标志:0=未删除;1=已逻辑删除。 | 来源: is_delete';
+ COMMENT ON COLUMN dwd_refund_Ex.check_status IS '审核状态。样本全部为 1(已审核/通过)。 | 来源: check_status';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_channel IS '线上支付渠道枚举。样本中全部为 0(线下或默认)。 | 来源: online_pay_channel';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_type IS '在线退款类型。样本全部为 0(原路退回)。 | 来源: online_pay_type';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_terminal IS '退款终端类型。样本全部为 1(前台收银端)。 | 来源: pay_terminal';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_config_id IS '支付配置 ID,例如某个具体支付通道(微信商户号、银联通道等)的配置主键。样本全部为 0。 | 来源: pay_config_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.cashier_point_id IS '收银点编号,例如前台1、前台2、自助机等。样本全部为 0。 | 来源: cashier_point_id';
+ COMMENT ON COLUMN dwd_refund_Ex.operator_id IS '执行退款操作的操作员 ID。样本全部为 0。 | 来源: operator_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_payer_id IS '支付渠道侧的付款人标识,如 openid、银行卡号掩码等。样本全部为空字符串。 | 来源: channel_payer_id';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_pay_no IS '第三方支付平台交易号(如微信支付单号、支付宝交易号等)。当前样本全部为空。 | 来源: channel_pay_no';
diff --git a/tmp/etl_billiards_misc/tmp & Delete/schema_v2.sql b/tmp/etl_billiards_misc/tmp & Delete/schema_v2.sql
new file mode 100644
index 0000000..f16cca2
--- /dev/null
+++ b/tmp/etl_billiards_misc/tmp & Delete/schema_v2.sql
@@ -0,0 +1,1772 @@
+-- Data warehouse schema for the entertainment chain (ODS -> DWD -> DWS)
+-- ASCII only to keep cross-platform friendly.
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+CREATE SCHEMA IF NOT EXISTS billiards_dwd;
+CREATE SCHEMA IF NOT EXISTS billiards_dws;
+
+-- ---------- ODS (raw, lightly typed) ----------
+-- Each ODS table keeps the source payload for replay/debug while exposing key fields.
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ member_id BIGINT NOT NULL,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ member_name TEXT,
+ nickname TEXT,
+ mobile TEXT,
+ gender TEXT,
+ birthday DATE,
+ register_time TIMESTAMPTZ,
+ member_type_id BIGINT,
+ member_type_name TEXT,
+ member_card_grade_code TEXT,
+ status TEXT,
+ user_status TEXT,
+ balance NUMERIC(18,2),
+ points NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ last_visit_time TIMESTAMPTZ,
+ wechat_id TEXT,
+ alipay_id TEXT,
+ member_card_no TEXT,
+ referrer_member_id BIGINT,
+ remarks TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, member_id)
+);
+COMMENT ON TABLE billiards_ods.member_profiles IS '鏉ユ簮锛氫細鍛樻。妗?json -> data.tenantMemberInfos锛涗竴鏉¤褰曚唬琛ㄢ€滅鎴峰唴涓€寮犱細鍛樺崱璐︽埛鈥?;
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_id IS '浠?register_site_id 琛ュ叆锛涙敞鍐岄棬搴桰D锛堟湰鎵逛负鍗曞簵锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.member_id IS '婧愬瓧娈?id锛涚鎴峰唴浼氬憳璐︽埛涓婚敭锛堝搴斿崱璐︽埛/妗fID锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '婧愬瓧娈?system_member_id锛涘叏骞冲彴浼氬憳ID锛屽彲璺ㄥ簵鑱氬悎鍚屼竴浜?;
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '婧愬瓧娈?register_site_id锛涘姙鍗?娉ㄥ唽闂ㄥ簵ID';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '婧愬瓧娈?site_name锛涘姙鍗¢棬搴楀悕绉板揩鐓?;
+COMMENT ON COLUMN billiards_ods.member_profiles.member_name IS '婧愭暟鎹湭鎻愪緵锛涢鐣欎細鍛樺疄鍚?;
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '婧愬瓧娈?nickname锛涗細鍛樻樉绀哄悕/鏄电О';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '婧愬瓧娈?mobile锛涗細鍛樻墜鏈哄彿';
+COMMENT ON COLUMN billiards_ods.member_profiles.gender IS '婧愭暟鎹湭鎻愪緵锛涢鐣欐€у埆';
+COMMENT ON COLUMN billiards_ods.member_profiles.birthday IS '婧愭暟鎹湭鎻愪緵锛涢鐣欑敓鏃?;
+COMMENT ON COLUMN billiards_ods.member_profiles.register_time IS '婧愬瓧娈?create_time锛涜处鎴峰垱寤烘椂闂?;
+COMMENT ON COLUMN billiards_ods.member_profiles.member_type_id IS '婧愭暟鎹湭鎻愪緵锛涢鐣欎細鍛樼被鍨?绛夌骇ID';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_type_name IS '婧愭暟鎹湭鎻愪緵锛涢鐣欎細鍛樼被鍨?绛夌骇鍚嶇О';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '婧愬瓧娈?member_card_grade_code锛涘崱绉?绛夌骇缂栫爜锛堝偍鍊煎崱/鍙拌垂鍗?鏈堝崱/娲诲姩鍒哥瓑锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '婧愬瓧娈?status锛涘崱璐︽埛鐘舵€侊紙1姝e父锛屽叾浠栦负鍋滅敤/浣滃簾锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '婧愬瓧娈?user_status锛涚敤鎴峰眰鐘舵€侊紙1姝e父锛?绂佺敤绛夛級';
+COMMENT ON COLUMN billiards_ods.member_profiles.balance IS '婧愭暟鎹湭鎻愪緵锛涢鐣欎綑棰濆揩鐓э紙瀹為檯浣欓鍦ㄥ崱琛級';
+COMMENT ON COLUMN billiards_ods.member_profiles.points IS '婧愬瓧娈?point锛涘綋鍓嶇Н鍒嗕綑棰濓紙鏈壒涓?锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '婧愬瓧娈?growth_value锛涙垚闀垮€?缁忛獙鍊硷紙鏈壒涓?锛?;
+COMMENT ON COLUMN billiards_ods.member_profiles.last_visit_time IS '婧愭暟鎹湭鎻愪緵锛涢鐣欐渶杩戝埌搴楁椂闂?;
+COMMENT ON COLUMN billiards_ods.member_profiles.wechat_id IS '婧愭暟鎹湭鎻愪緵锛涢鐣欏井淇D';
+COMMENT ON COLUMN billiards_ods.member_profiles.alipay_id IS '婧愭暟鎹湭鎻愪緵锛涢鐣欐敮浠樺疂ID';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_no IS '婧愭暟鎹湭鎻愪緵锛涢鐣欏疄浣撳崱鍙?;
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '婧愬瓧娈?referrer_member_id锛涙帹鑽愪汉浼氬憳ID锛?琛ㄧず鏃狅級';
+COMMENT ON COLUMN billiards_ods.member_profiles.remarks IS '婧愭暟鎹湭鎻愪緵锛涢鐣欏娉?;
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ card_id BIGINT NOT NULL,
+ member_id BIGINT,
+ tenant_member_id BIGINT,
+ card_type_id BIGINT,
+ card_type_name TEXT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ card_balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ discount_rate NUMERIC(8,4),
+ table_discount NUMERIC(18,2),
+ goods_discount NUMERIC(18,2),
+ assistant_discount NUMERIC(18,2),
+ assistant_reward_discount NUMERIC(18,2),
+ valid_start_date DATE,
+ valid_end_date DATE,
+ disable_start_date DATE,
+ disable_end_date DATE,
+ last_consume_time TIMESTAMPTZ,
+ status TEXT,
+ is_delete BOOLEAN,
+ activate_time TIMESTAMPTZ,
+ deactivate_time TIMESTAMPTZ,
+ register_site_id BIGINT,
+ issuer_id BIGINT,
+ issuer_name TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, card_id)
+);
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '鏉ユ簮锛氬偍鍊煎崱鍒楄〃.json -> data.tenantMemberCards锛涘寘鍚偍鍊煎崱/鍙拌垂鍗?鏈堝崱/娲诲姩鍒哥瓑浼氬憳鍗″畾涔変笌浣欓';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_id IS '婧愬瓧娈?register_site_id锛涘紑鍗¢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_id IS '婧愬瓧娈?id锛涗細鍛樺崱璐︽埛ID';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_id IS '婧愬瓧娈?system_member_id锛涘钩鍙颁細鍛業D锛堟湭缁戝畾鏃朵负0锛?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '婧愬瓧娈?tenant_member_id锛涚鎴峰唴浼氬憳ID';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '婧愬瓧娈?card_type_id锛涘崱绉岻D';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_name IS '婧愬瓧娈?member_card_type_name锛涘崱绉嶅悕绉?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '婧愬瓧娈?card_no锛涘疄浣?铏氭嫙鍗″彿锛堟湰鎵逛负绌猴級';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '婧愬瓧娈?card_physics_type锛涚墿鐞嗗崱绫诲瀷鏋氫妇锛堟湰鎵逛负1锛?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_balance IS '婧愬瓧娈?balance锛涘綋鍓嶅崱鍐呬綑棰?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '婧愬瓧娈?denomination锛涢潰棰?鍒濆鍌ㄥ€奸搴?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.discount_rate IS '婧愭暟鎹湭鎷嗗嚭缁熶竴鎶樻墸锛涘悇鍦烘櫙鎶樻墸瑙?table/goods/assistant 瀛楁';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '婧愬瓧娈?table_discount锛涘彴璐规姌鎵o紝10琛ㄧず涓嶆墦鎶?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '婧愬瓧娈?goods_discount锛涘晢鍝佹姌鎵?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '婧愬瓧娈?assistant_discount锛涘姪鏁欐湇鍔℃姌鎵?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '婧愬瓧娈?assistant_reward_discount锛涘姪鏁欏鍔遍噾鎶樻墸';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.valid_start_date IS '婧愬瓧娈?start_time锛涘崱鏈夋晥鏈熻捣';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.valid_end_date IS '婧愬瓧娈?end_time锛涘崱鏈夋晥鏈熸';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_date IS '婧愬瓧娈?disable_start_time锛涘仠鐢ㄥ紑濮嬫椂闂达紙鏈壒榛樿0001-01-01锛?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_date IS '婧愬瓧娈?disable_end_time锛涘仠鐢ㄧ粨鏉熸椂闂?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '婧愬瓧娈?last_consume_time锛涙渶杩戞秷璐规椂闂?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '婧愬瓧娈?status锛涘崱鐘舵€侊紙1姝e父锛?杩囨湡/鍋滅敤绛夛級';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '婧愬瓧娈?is_delete锛涢€昏緫鍒犻櫎鏍囪';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.activate_time IS '婧愬瓧娈?create_time锛涘紑鍗℃椂闂?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deactivate_time IS '婧愭暟鎹湭鎻愪緵锛涢鐣欐敞閿€/鍋滅敤鏃堕棿';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '婧愬瓧娈?register_site_id锛涘紑鍗¢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.issuer_id IS '婧愭暟鎹湭鎻愪緵锛涢鐣欏紑鍗℃搷浣滀汉ID';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.issuer_name IS '婧愭暟鎹湭鎻愪緵锛涢鐣欏紑鍗℃搷浣滀汉鍚嶇О';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ change_id BIGINT NOT NULL,
+ member_id BIGINT,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ member_name TEXT,
+ member_mobile TEXT,
+ change_amount NUMERIC(18,2),
+ balance_before NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ change_type INT,
+ payment_method INT,
+ refund_amount NUMERIC(18,2),
+ relate_id BIGINT,
+ register_site_id BIGINT,
+ register_site_name TEXT,
+ pay_site_name TEXT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ change_time TIMESTAMPTZ,
+ is_deleted BOOLEAN DEFAULT FALSE,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, change_id)
+);
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS 'Source: 搴撳瓨鍙樺寲璁板綍1.json -> data.queryDeliveryRecordsList';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenant_id IS 'source: queryDeliveryRecordsList.tenantId; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.site_id IS 'source: queryDeliveryRecordsList.siteId; store id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.change_id IS 'source: queryDeliveryRecordsList.siteGoodsStockId; stock change record id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.site_goods_id IS 'source: queryDeliveryRecordsList.siteGoodsId; site goods id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goods_id IS 'not present in export; reserved for tenant goods id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stock_type IS 'source: queryDeliveryRecordsList.stockType; stock change type';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.change_amount IS 'source: queryDeliveryRecordsList.changeNum; change amount (primary unit)';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.before_stock IS 'source: queryDeliveryRecordsList.startNum; stock before change';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.after_stock IS 'source: queryDeliveryRecordsList.endNum; stock after change';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.change_amount_alt IS 'source: queryDeliveryRecordsList.changeNumA; alt unit change amount';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.before_stock_alt IS 'source: queryDeliveryRecordsList.startNumA; alt unit stock before';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.after_stock_alt IS 'source: queryDeliveryRecordsList.endNumA; alt unit stock after';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.change_type IS 'source: queryDeliveryRecordsList.stockType; stock change type enum';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.relate_id IS 'not present in export; reserved for related business id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS 'source: queryDeliveryRecordsList.unit; unit name';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS 'source: queryDeliveryRecordsList.price; unit price';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goods_category_id IS 'source: queryDeliveryRecordsList.goodsCategoryId; category id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goods_second_category_id IS 'source: queryDeliveryRecordsList.goodsSecondCategoryId; second category id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS 'source: queryDeliveryRecordsList.remark; remark';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operator_id IS 'not present in export; reserved for operator id';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operator_name IS 'source: queryDeliveryRecordsList.operatorName; operator name';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.change_time IS 'source: queryDeliveryRecordsList.createTime; change time';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS 'raw JSON payload for replay/debug';
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '鏉ユ簮锛氫綑棰濆彉鏇磋褰?json -> data.tenantMemberCardLogs锛涜褰曟瘡娆″崱浣欓澧炲噺';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '婧愬瓧娈?site_id锛涘彂鐢熷彉鍔ㄧ殑闂ㄥ簵ID锛?琛ㄧず骞冲彴/璺ㄥ簵璋冩暣锛?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.change_id IS '婧愬瓧娈?id锛涗綑棰濆彉鏇磋褰曚富閿?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.member_id IS '婧愬瓧娈?system_member_id锛涘钩鍙颁細鍛業D';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '婧愬瓧娈?tenant_member_id锛涚鎴峰唴浼氬憳ID';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '婧愬瓧娈?tenant_member_card_id锛涗細鍛樺崱璐︽埛ID';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.member_name IS '婧愬瓧娈?memberName锛涗細鍛樺鍚嶅揩鐓?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.member_mobile IS '婧愬瓧娈?memberMobile锛涗細鍛樻墜鏈哄彿蹇収';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.change_amount IS '婧愬瓧娈?account_data锛涙湰娆″彉鍔ㄩ噾棰濓紝姝e姞璐熷噺';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.balance_before IS '婧愬瓧娈?before锛涘彉鍔ㄥ墠浣欓';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.balance_after IS '婧愬瓧娈?after锛涘彉鍔ㄥ悗浣欓';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.change_type IS '婧愬瓧娈?from_type锛涘彉鍔ㄦ潵婧愮被鍨嬫灇涓?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '婧愬瓧娈?payment_method锛涙敮浠樻柟寮忔灇涓?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '婧愬瓧娈?refund_amount锛涢€€娆鹃噾棰濓紙鏍锋湰涓?锛?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '婧愬瓧娈?relate_id锛涘叧鑱斾笟鍔D锛堝厖鍊?缁撶畻/娲诲姩绛夛級';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '婧愬瓧娈?register_site_id锛涘姙鍗¢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_name IS '婧愬瓧娈?registerSiteName锛涘姙鍗¢棬搴楀悕绉?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.pay_site_name IS '婧愬瓧娈?paySiteName锛涙湰娆″彂鐢熼棬搴楀悕绉?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '婧愬瓧娈?remark锛涘娉?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '婧愬瓧娈?operator_id锛涙搷浣滃憳ID';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '婧愬瓧娈?operator_name锛涙搷浣滃憳鍚嶇О';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.change_time IS '婧愬瓧娈?create_time锛涘彉鍔ㄦ椂闂?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_deleted IS '婧愬瓧娈?is_delete锛涢€昏緫鍒犻櫎鏍囪';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_recharge_record (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ recharge_id BIGINT NOT NULL,
+ member_id BIGINT,
+ recharge_amount NUMERIC(18,2),
+ gift_amount NUMERIC(18,2),
+ pay_method INT,
+ pay_trade_no TEXT,
+ order_trade_no TEXT,
+ recharge_time TIMESTAMPTZ,
+ status TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, recharge_id)
+);
+COMMENT ON TABLE billiards_ods.ods_recharge_record IS '鏉ユ簮锛氬厖鍊艰褰?json -> data.settleList[].settleList锛涙部鐢ㄧ粨绠楀崟妯″瀷鐨勫厖鍊兼祦姘?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.tenant_id IS '婧愬瓧娈?tenantId锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.site_id IS '婧愬瓧娈?siteId锛涘厖鍊煎彂鐢熼棬搴?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.recharge_id IS '婧愬瓧娈?id锛涘厖鍊艰褰旾D';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.member_id IS '婧愬瓧娈?memberId锛涗細鍛業D锛堝彲涓?琛ㄧず鏈粦浼氬憳锛?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.recharge_amount IS '婧愬瓧娈?payAmount锛涙湰娆″厖鍊兼敮浠橀噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.gift_amount IS '婧愬瓧娈?giftCardAmount锛涜禒閫侀噾棰濓紙鏍锋湰涓?锛?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.pay_method IS '婧愬瓧娈?paymentMethod锛涙敮浠樻柟寮忔灇涓?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.pay_trade_no IS '婧愭暟鎹湭缁欙紱棰勭暀澶栭儴浜ゆ槗鍙?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.order_trade_no IS '婧愬瓧娈?settleRelateId 鍙槧灏勶紱鍏宠仈涓氬姟鍗曞彿';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.recharge_time IS '婧愬瓧娈?payTime锛涙敮浠樻椂闂?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.status IS '婧愬瓧娈?settleStatus锛涘厖鍊肩姸鎬侊紙2鎴愬姛绛夛級';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.operator_id IS '婧愬瓧娈?operatorId锛涙搷浣滃憳ID';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.operator_name IS '婧愬瓧娈?operatorName锛涙搷浣滃憳鍚嶇О';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_recharge_record.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_product (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ goods_id BIGINT NOT NULL,
+ goods_name TEXT,
+ goods_code TEXT,
+ category_id BIGINT,
+ category_name TEXT,
+ goods_second_category_id BIGINT,
+ unit TEXT,
+ price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ market_price NUMERIC(18,2),
+ goods_state TEXT,
+ goods_cover TEXT,
+ goods_bar_code TEXT,
+ able_discount BOOLEAN,
+ is_delete BOOLEAN,
+ status TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, goods_id)
+);
+COMMENT ON TABLE billiards_ods.ods_product IS '鏉ユ簮锛氬晢鍝佹。妗?json -> data.tenantGoodsList锛涚鎴风骇鍟嗗搧鍩虹淇℃伅';
+COMMENT ON COLUMN billiards_ods.ods_product.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_product.site_id IS '婧愭暟鎹湭缁欙紱鍟嗗搧涓虹鎴风骇锛屾寜閲囬泦涓婁笅鏂囪祴鍊?;
+COMMENT ON COLUMN billiards_ods.ods_product.goods_id IS '婧愬瓧娈?id锛涚鎴峰晢鍝両D';
+COMMENT ON COLUMN billiards_ods.ods_product.goods_name IS '婧愬瓧娈?goods_name锛涘晢鍝佸悕绉?;
+COMMENT ON COLUMN billiards_ods.ods_product.goods_code IS '婧愬瓧娈?commodityCode/commodity_code锛涘唴閮ㄧ紪鐮?鏉$爜';
+COMMENT ON COLUMN billiards_ods.ods_product.category_id IS '婧愬瓧娈?goods_category_id锛涗竴绾у垎绫籌D';
+COMMENT ON COLUMN billiards_ods.ods_product.category_name IS '婧愬瓧娈?categoryName锛涗竴绾у垎绫诲悕绉?;
+COMMENT ON COLUMN billiards_ods.ods_product.goods_second_category_id IS '婧愬瓧娈?goods_second_category_id锛涗簩绾у垎绫籌D';
+COMMENT ON COLUMN billiards_ods.ods_product.unit IS '婧愬瓧娈?unit锛涜閲忓崟浣?;
+COMMENT ON COLUMN billiards_ods.ods_product.price IS '婧愭暟鎹湭鐩存帴缁欙紱鍙寜 market_price/min_discount_price 琛ュ厖';
+COMMENT ON COLUMN billiards_ods.ods_product.cost_price IS '婧愬瓧娈?cost_price锛涙垚鏈环';
+COMMENT ON COLUMN billiards_ods.ods_product.market_price IS '婧愬瓧娈?market_price锛涘競鍦?鏍囦环';
+COMMENT ON COLUMN billiards_ods.ods_product.goods_state IS '婧愬瓧娈?goods_state锛涗笂鏋剁姸鎬?;
+COMMENT ON COLUMN billiards_ods.ods_product.goods_cover IS '婧愬瓧娈?goods_cover锛涘晢鍝佸浘鐗嘦RL';
+COMMENT ON COLUMN billiards_ods.ods_product.goods_bar_code IS '婧愬瓧娈?goods_bar_code锛涙潯鐮?;
+COMMENT ON COLUMN billiards_ods.ods_product.able_discount IS '婧愬瓧娈?able_discount锛涙槸鍚﹀彲鎵撴姌';
+COMMENT ON COLUMN billiards_ods.ods_product.is_delete IS '婧愬瓧娈?is_delete锛涢€昏緫鍒犻櫎鏍囪';
+COMMENT ON COLUMN billiards_ods.ods_product.status IS '涓?goods_state 瀵归綈鐨勯€氱敤鐘舵€?;
+COMMENT ON COLUMN billiards_ods.ods_product.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_product.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_product.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_product.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_store_product (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ site_goods_id BIGINT NOT NULL,
+ goods_id BIGINT,
+ goods_name TEXT,
+ category_id BIGINT,
+ category_name TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ sale_num NUMERIC(18,2),
+ stock_a NUMERIC(18,2),
+ stock NUMERIC(18,2),
+ provisional_total_cost NUMERIC(18,2),
+ total_purchase_cost NUMERIC(18,2),
+ batch_stock_quantity NUMERIC(18,2),
+ goods_state TEXT,
+ status TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, site_goods_id)
+);
+COMMENT ON TABLE billiards_ods.ods_store_product IS '鏉ユ簮锛氶棬搴楀晢鍝佹。妗?.json -> data.orderGoodsList锛涢棬搴楃淮搴﹀晢鍝佽鍥?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_store_product.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.ods_store_product.site_goods_id IS '婧愬瓧娈?id锛涢棬搴楀晢鍝両D';
+COMMENT ON COLUMN billiards_ods.ods_store_product.goods_id IS '婧愬瓧娈?tenant_goods_id锛涚鎴风骇鍟嗗搧ID';
+COMMENT ON COLUMN billiards_ods.ods_store_product.goods_name IS '婧愬瓧娈?goods_name锛涘晢鍝佸悕绉?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.category_id IS '婧愬瓧娈?goods_category_id锛涘垎绫籌D';
+COMMENT ON COLUMN billiards_ods.ods_store_product.category_name IS '婧愬瓧娈?twoCategoryName/oneCategoryName锛涘垎绫诲悕绉板揩鐓?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.unit IS '婧愬瓧娈?unit锛涜閲忓崟浣?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.sale_price IS '婧愬瓧娈?sale_price锛涢攢鍞环';
+COMMENT ON COLUMN billiards_ods.ods_store_product.cost_price IS '婧愬瓧娈?cost_price锛涙垚鏈环';
+COMMENT ON COLUMN billiards_ods.ods_store_product.sale_num IS '婧愬瓧娈?sale_num锛涚疮璁¢攢閲?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.stock_a IS '婧愬瓧娈?stock_A锛涘鐢ㄥ簱瀛樻暟閲?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.stock IS '婧愬瓧娈?stock锛涘綋鍓嶅簱瀛?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.provisional_total_cost IS '婧愬瓧娈?provisional_total_cost锛涙殏浼板簱瀛樻垚鏈?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.total_purchase_cost IS '婧愬瓧娈?total_purchase_cost锛涜繘璐ф€绘垚鏈?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.batch_stock_quantity IS '婧愬瓧娈?batch_stock_quantity锛涙壒娆″簱瀛樻暟閲?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.goods_state IS '婧愬瓧娈?goods_state锛涘晢鍝佺姸鎬?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.status IS '婧愬瓧娈?enable_status锛涗笂涓嬫灦鐘舵€?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_store_product.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_store_product.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_store_product.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_store_sale_item (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ sale_item_id BIGINT NOT NULL,
+ order_goods_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ site_goods_id BIGINT,
+ goods_id BIGINT,
+ goods_name TEXT,
+ category_id BIGINT,
+ quantity NUMERIC(18,4),
+ unit_price NUMERIC(18,2),
+ original_amount NUMERIC(18,2),
+ discount_amount NUMERIC(18,2),
+ final_amount NUMERIC(18,2),
+ is_gift BOOLEAN DEFAULT FALSE,
+ sale_time TIMESTAMPTZ,
+ member_id BIGINT,
+ salesman_id BIGINT,
+ operator_id BIGINT,
+ is_refunded BOOLEAN DEFAULT FALSE,
+ discount_price NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ coupon_deduct_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ sales_type TEXT,
+ goods_remark TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, sale_item_id)
+);
+COMMENT ON TABLE billiards_ods.ods_store_sale_item IS '鏉ユ簮锛氶棬搴楀晢鍝侀攢鍞褰?json -> data.orderGoodsLedgers锛涘晢鍝佹槑缁嗘祦姘?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.sale_item_id IS '婧愬瓧娈?id锛涘晢鍝佹槑缁嗘祦姘碔D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.order_goods_id IS '婧愬瓧娈?order_goods_id锛涗笂娓歌鍗曞晢鍝両D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.order_trade_no IS '婧愬瓧娈?order_trade_no锛涗笟鍔¤鍗曞彿';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.order_settle_id IS '婧愬瓧娈?order_settle_id锛涚粨绠楀崟ID';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.site_goods_id IS '婧愬瓧娈?site_goods_id锛涢棬搴楀晢鍝両D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.goods_id IS '婧愬瓧娈?tenant_goods_id锛涚鎴风骇鍟嗗搧ID';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.goods_name IS '婧愬瓧娈?ledger_name锛涘晢鍝佸悕绉板揩鐓?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.category_id IS '婧愬瓧娈?tenant_goods_category_id锛涘晢鍝佸垎绫籌D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.quantity IS '婧愬瓧娈?ledger_count锛涢攢鍞暟閲?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.unit_price IS '婧愬瓧娈?ledger_unit_price锛涚粨绠楀崟浠?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.original_amount IS '婧愬瓧娈?ledger_amount锛涘師濮嬮噾棰濓紙鏈墸鍑忥級';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.discount_amount IS '婧愬瓧娈?discount_money锛涙姌鎵i噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.final_amount IS '婧愬瓧娈?real_goods_money锛涙姌鍚庡疄鏀堕噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.is_gift IS '鐢?sales_type/ledger_status 鎺ㄥ锛涜禒閫?閫€璐у満鏅爣璁?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.sale_time IS '婧愬瓧娈?create_time锛涢攢鍞椂闂?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.member_id IS '婧愭暟鎹湭缁欙紱棰勭暀浼氬憳ID';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.salesman_id IS '婧愬瓧娈?salesman_user_id锛涢攢鍞憳ID';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.operator_id IS '婧愬瓧娈?operator_id锛涙敹閾?鎿嶄綔鍛業D';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.is_refunded IS '鐢?returns_number>0 鎴?ledger_status 鍒ゆ柇锛涢€€璐ф爣璁?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.discount_price IS '婧愬瓧娈?discount_price锛涙姌鍚庡崟浠凤紙濡傛湁锛?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.cost_money IS '婧愬瓧娈?cost_money锛涙垚鏈噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.coupon_deduct_amount IS '婧愬瓧娈?coupon_deduct_money + option_coupon_deduct_money锛涘埜鎶垫墸閲戦';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.member_discount_amount IS '婧愬瓧娈?member_discount_amount锛涗細鍛樻姌鎵i噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.point_discount_money IS '婧愬瓧娈?point_discount_money锛涚Н鍒嗘姷鎵i噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.point_discount_cost IS '婧愬瓧娈?point_discount_money_cost锛涚Н鍒嗘姷鎵f垚鏈?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.sales_type IS '婧愬瓧娈?sales_type锛涢攢鍞被鍨嬫灇涓?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.goods_remark IS '婧愬瓧娈?goods_remark锛涘晢鍝佸娉?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_store_sale_item.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_info (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ table_id BIGINT NOT NULL,
+ table_code TEXT,
+ table_name TEXT,
+ table_type TEXT,
+ area_name TEXT,
+ site_table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_price NUMERIC(18,2),
+ table_status TEXT,
+ audit_status INT,
+ show_status INT,
+ light_status INT,
+ virtual_table BOOLEAN,
+ is_rest_area BOOLEAN,
+ charge_free BOOLEAN,
+ table_cloth_use_time INT,
+ table_cloth_use_cycle INT,
+ status TEXT,
+ created_time TIMESTAMPTZ,
+ updated_time TIMESTAMPTZ,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, table_id)
+);
+COMMENT ON TABLE billiards_ods.ods_table_info IS '鏉ユ簮锛氬彴妗屽垪琛?json -> data.siteTables锛涢棬搴楃悆妗?鍖呭帰妗f';
+COMMENT ON COLUMN billiards_ods.ods_table_info.tenant_id IS '婧愭暟鎹湭缁欙紱鎸夐噰闆嗕笂涓嬫枃璁剧疆';
+COMMENT ON COLUMN billiards_ods.ods_table_info.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_id IS '婧愬瓧娈?id锛涚悆妗?鍖呭帰ID';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_code IS '婧愭暟鎹湭缁欙紱棰勭暀鍐呴儴缂栧彿';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_name IS '婧愬瓧娈?table_name锛涙鍙?鍚嶇О';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_type IS '婧愭暟鎹湭缁欙紱棰勭暀妗屽瀷';
+COMMENT ON COLUMN billiards_ods.ods_table_info.area_name IS '婧愬瓧娈?areaName锛涙墍灞炲尯鍩熷悕绉?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.site_table_area_id IS '婧愬瓧娈?site_table_area_id锛涢棬搴楀尯鍩烮D';
+COMMENT ON COLUMN billiards_ods.ods_table_info.tenant_table_area_id IS '婧愭暟鎹湭缁欙紱棰勭暀绉熸埛绾у尯鍩烮D';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_price IS '婧愬瓧娈?table_price锛涘熀纭€鍙拌垂鍗曚环';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_status IS '婧愬瓧娈?table_status锛涘綋鍓嶆鐘舵€?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.audit_status IS '婧愬瓧娈?audit_status锛涘鏍哥姸鎬?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.show_status IS '婧愬瓧娈?show_status锛涙樉绀虹姸鎬?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.light_status IS '婧愬瓧娈?light_status锛涚伅鎺х姸鎬?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.virtual_table IS '婧愬瓧娈?virtual_table锛涙槸鍚﹁櫄鎷熸';
+COMMENT ON COLUMN billiards_ods.ods_table_info.is_rest_area IS '婧愬瓧娈?is_rest_area锛涙槸鍚︿紤鎭尯';
+COMMENT ON COLUMN billiards_ods.ods_table_info.charge_free IS '婧愬瓧娈?charge_free锛涙槸鍚﹀厤璐?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_cloth_use_time IS '婧愬瓧娈?table_cloth_use_time锛涘彴鍛㈠凡鐢ㄦ椂闀匡紙绉掞級';
+COMMENT ON COLUMN billiards_ods.ods_table_info.table_cloth_use_cycle IS '婧愬瓧娈?table_cloth_use_Cycle锛涘彴鍛㈡洿鎹㈠懆鏈熼槇鍊硷紙绉掞級';
+COMMENT ON COLUMN billiards_ods.ods_table_info.status IS '閫氱敤鐘舵€侊紱鍙粨鍚?table_status/show_status 浣跨敤';
+COMMENT ON COLUMN billiards_ods.ods_table_info.created_time IS '婧愬瓧娈?create_time锛涘垱寤烘椂闂?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.updated_time IS '婧愭暟鎹湭缁欙紱棰勭暀鏇存柊鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_table_info.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_table_info.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_table_info.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_table_info.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions_log (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ ledger_id BIGINT NOT NULL,
+ table_id BIGINT,
+ table_name TEXT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ duration_seconds INT,
+ billing_unit_price NUMERIC(18,4),
+ billing_count NUMERIC(18,4),
+ original_table_fee NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_discount_amount NUMERIC(18,2),
+ manual_discount_amount NUMERIC(18,2),
+ service_fee NUMERIC(18,2),
+ final_table_fee NUMERIC(18,2),
+ member_id BIGINT,
+ operator_id BIGINT,
+ salesman_id BIGINT,
+ is_canceled BOOLEAN DEFAULT FALSE,
+ cancel_time TIMESTAMPTZ,
+ site_table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ is_single_order BOOLEAN,
+ used_card_amount NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ real_table_use_seconds INT,
+ last_use_time TIMESTAMPTZ,
+ ledger_start_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ ledger_status INT,
+ start_use_time TIMESTAMPTZ,
+ add_clock_seconds INT,
+ status TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, ledger_id)
+);
+COMMENT ON TABLE billiards_ods.ods_assistant_service_log IS 'Source: 鍔╂暀娴佹按.json -> data.orderAssistantDetails';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.tenant_id IS 'source: orderAssistantDetails.tenant_id; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.site_id IS 'source: orderAssistantDetails.site_id; store id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.ledger_id IS 'source: orderAssistantDetails.id; assistant service ledger id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.assistant_id IS 'source: orderAssistantDetails.site_assistant_id; assistant id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.assistant_name IS 'source: orderAssistantDetails.assistantName; assistant name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.service_type IS 'source: orderAssistantDetails.order_assistant_type; service type code';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.order_trade_no IS 'source: orderAssistantDetails.order_trade_no; business order number';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.order_settle_id IS 'source: orderAssistantDetails.order_settle_id; settlement id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.start_time IS 'source: orderAssistantDetails.start_use_time; service start time';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.end_time IS 'source: orderAssistantDetails.ledger_end_time; service end time';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.duration_seconds IS 'source: orderAssistantDetails.real_use_seconds; actual service seconds';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.original_fee IS 'source: orderAssistantDetails.ledger_amount; amount before discounts';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.member_discount_amount IS 'source: orderAssistantDetails.member_discount_amount; member discount amount';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.manual_discount_amount IS 'source: orderAssistantDetails.manual_discount_amount; manual discount';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.coupon_discount_amount IS 'source: orderAssistantDetails.coupon_deduct_money; coupon deduction';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.final_fee IS 'source: orderAssistantDetails.service_money; final assistant fee';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.member_id IS 'source: orderAssistantDetails.system_member_id; member id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.operator_id IS 'source: orderAssistantDetails.operator_id; operator id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.salesman_id IS 'source: orderAssistantDetails.salesman_user_id; salesperson id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.is_canceled IS 'derived; set when is_delete/is_trash indicates cancellation';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.cancel_time IS 'not present in export; reserved for cancel time';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.skill_grade IS 'source: orderAssistantDetails.skill_grade; skill grade score';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.service_grade IS 'source: orderAssistantDetails.service_grade; service grade score';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.composite_grade IS 'source: orderAssistantDetails.composite_grade; composite score';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.overall_score IS 'source: orderAssistantDetails.sum_grade; overall score sum';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.status IS 'source: orderAssistantDetails.ledger_status/grade_status; status flag';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.ods_assistant_service_log.payload IS 'raw JSON payload for replay/debug';
+COMMENT ON TABLE billiards_ods.table_fee_transactions_log IS '鏉ユ簮锛氬彴璐规祦姘?json -> data.siteTableUseDetailsList锛涘彴璐硅璐规祦姘?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.ledger_id IS '婧愬瓧娈?id锛涘彴璐硅处鍗旾D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.table_id IS '婧愬瓧娈?site_table_id锛涚悆妗孖D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.table_name IS '婧愬瓧娈?ledger_name锛涙鍚嶅揩鐓?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.order_trade_no IS '婧愬瓧娈?order_trade_no锛涗笟鍔¤鍗曞彿';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.order_settle_id IS '婧愬瓧娈?order_settle_id锛涚粨绠楀崟ID';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.start_time IS '婧愬瓧娈?ledger_start_time锛涜璐瑰紑濮嬫椂闂?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.end_time IS '婧愬瓧娈?ledger_end_time锛涜璐圭粨鏉熸椂闂?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.duration_seconds IS '婧愬瓧娈?ledger_count锛涜璐规椂闀?鏁伴噺锛堢锛?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.billing_unit_price IS '婧愬瓧娈?ledger_unit_price锛涜璐瑰崟浠?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.billing_count IS '婧愬瓧娈?ledger_count锛涜璐规暟閲?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.original_table_fee IS '婧愬瓧娈?ledger_amount锛涙姌鎵e墠閲戦';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.member_discount_amount IS '婧愬瓧娈?member_discount_amount锛涗細鍛樻姌鎵?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.coupon_discount_amount IS '婧愬瓧娈?coupon_promotion_amount锛涘埜鎶垫墸';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.manual_discount_amount IS '婧愬瓧娈?adjust_amount锛涙墜宸ヤ紭鎯?璋冩暣';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.service_fee IS '婧愬瓧娈?service_money锛涙湇鍔¤垂';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.final_table_fee IS '婧愬瓧娈?real_table_charge_money锛涙渶缁堝彴璐?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.member_id IS '婧愬瓧娈?member_id锛涗細鍛業D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.operator_id IS '婧愬瓧娈?operator_id锛涙搷浣滃憳ID';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.salesman_id IS '婧愬瓧娈?salesman_user_id锛涢攢鍞憳ID';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.is_canceled IS '鐢?ledger_status/is_delete 鎺ㄥ锛涙槸鍚﹀彇娑?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.cancel_time IS '婧愭暟鎹湭缁欙紱棰勭暀鍙栨秷鏃堕棿';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.site_table_area_id IS '婧愬瓧娈?site_table_area_id锛涢棬搴楀尯鍩烮D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.tenant_table_area_id IS '婧愬瓧娈?tenant_table_area_id锛涚鎴峰尯鍩烮D';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.site_table_area_name IS '婧愬瓧娈?site_table_area_name锛涘尯鍩熷悕绉?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.is_single_order IS '婧愬瓧娈?is_single_order锛涘崟鍙?骞跺崟鏍囪';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.used_card_amount IS '婧愬瓧娈?used_card_amount锛涘崱鏀粯閲戦';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.adjust_amount IS '婧愬瓧娈?adjust_amount锛涜皟鏁撮噾棰?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.coupon_promotion_amount IS '婧愬瓧娈?coupon_promotion_amount锛涗紭鎯犲埜淇冮攢閲戦';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.service_money IS '婧愬瓧娈?service_money锛涙湇鍔¤垂閲戦';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.mgmt_fee IS '婧愬瓧娈?mgmt_fee锛涚鐞嗚垂';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.fee_total IS '婧愬瓧娈?fee_total锛涙€昏垂鐢紙鍚績閿€鍚庯級';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.real_table_use_seconds IS '婧愬瓧娈?real_table_use_seconds锛涘疄闄呬娇鐢ㄧ鏁?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.last_use_time IS '婧愬瓧娈?last_use_time锛涙渶杩戜娇鐢ㄧ粨鏉熸椂闂?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.ledger_start_time IS '婧愬瓧娈?ledger_start_time锛涜璐瑰紑濮?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.ledger_end_time IS '婧愬瓧娈?ledger_end_time锛涜璐圭粨鏉?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.ledger_status IS '婧愬瓧娈?ledger_status锛涜处鍗曠姸鎬?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.start_use_time IS '婧愬瓧娈?start_use_time锛涘疄闄呭紑濮嬬敤鍙版椂闂?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.add_clock_seconds IS '婧愬瓧娈?add_clock_seconds锛涢澶栬鏃剁鏁?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.status IS '閫氱敤鐘舵€侊紱缁撳悎 ledger_status/is_delete 鍒ゅ畾';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions_log.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_table_fee_adjust (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ adjust_id BIGINT NOT NULL,
+ ledger_id BIGINT,
+ order_trade_no TEXT,
+ discount_amount NUMERIC(18,2),
+ reason TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ created_at TIMESTAMPTZ,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, adjust_id)
+);
+COMMENT ON TABLE billiards_ods.ods_table_fee_adjust IS '鏉ユ簮锛氬彴璐规墦鎶?json -> data.taiFeeAdjustInfos锛涘彴璐规墜宸ユ姌鎵?璋冩暣璁板綍';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.adjust_id IS '婧愬瓧娈?id锛涘彴璐规姌鎵h褰旾D';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.ledger_id IS '婧愬瓧娈?order_settle_id锛涘叧鑱斿彴璐硅处鍗?缁撶畻ID';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.order_trade_no IS '婧愬瓧娈?order_trade_no锛涗笟鍔¤鍗曞彿';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.discount_amount IS '婧愬瓧娈?ledger_amount锛涙姌鎵i噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.reason IS '婧愬瓧娈?adjust_type/applicant_* 缁勫悎锛涜皟鏁村師鍥狅紙鏄庣粏闇€缁撳悎 payload锛?;
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.operator_id IS '婧愬瓧娈?operator_id锛涙搷浣滃憳ID';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.operator_name IS '婧愬瓧娈?operator_name锛涙搷浣滃憳鍚嶇О';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.created_at IS '婧愬瓧娈?create_time锛涘垱寤烘椂闂?;
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_table_fee_adjust.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ assistant_id BIGINT NOT NULL,
+ assistant_name TEXT,
+ mobile TEXT,
+ assistant_no INT,
+ team_id BIGINT,
+ team_name TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ job_num TEXT,
+ entry_type TEXT,
+ leave_status TEXT,
+ assistant_status TEXT,
+ allow_cx BOOLEAN,
+ status TEXT,
+ hired_date DATE,
+ left_date DATE,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, assistant_id)
+);
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS 'Source: 鍔╂暀璐﹀彿.json -> data.assistantInfos';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS 'source: assistantInfos.tenant_id; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS 'source: assistantInfos.site_id; store id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_id IS 'source: assistantInfos.id; assistant account id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_name IS 'source: assistantInfos.real_name; assistant real name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS 'source: assistantInfos.mobile; phone number';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS 'source: assistantInfos.assistant_no; assistant code';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS 'source: assistantInfos.team_id; team id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS 'source: assistantInfos.team_name; team name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS 'source: assistantInfos.group_id; group id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS 'source: assistantInfos.group_name; group name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS 'source: assistantInfos.job_num; job number';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS 'source: assistantInfos.entry_type; entry type enum';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS 'source: assistantInfos.leave_status; on-duty/off-duty status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS 'source: assistantInfos.assistant_status; account enable flag';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS 'source: assistantInfos.allow_cx; allow promotion/discount flag';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.status IS 'source: assistantInfos.show_status/work_status; general status flag';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.hired_date IS 'source: assistantInfos.entry_time; hire date';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.left_date IS 'source: assistantInfos.resign_time; resign date';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_service_log (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ ledger_id BIGINT NOT NULL,
+ assistant_id BIGINT,
+ assistant_name TEXT,
+ service_type TEXT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ duration_seconds INT,
+ original_fee NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ manual_discount_amount NUMERIC(18,2),
+ coupon_discount_amount NUMERIC(18,2),
+ final_fee NUMERIC(18,2),
+ member_id BIGINT,
+ operator_id BIGINT,
+ salesman_id BIGINT,
+ is_canceled BOOLEAN DEFAULT FALSE,
+ cancel_time TIMESTAMPTZ,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ composite_grade NUMERIC(10,2),
+ overall_score NUMERIC(10,2),
+ status TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, ledger_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_assistant_cancel_log (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ cancel_id BIGINT NOT NULL,
+ ledger_id BIGINT,
+ assistant_id BIGINT,
+ order_trade_no TEXT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_name TEXT,
+ assistant_on INT,
+ pd_charge_minutes INT,
+ assistant_abolish_amount NUMERIC(18,2),
+ reason TEXT,
+ cancel_time TIMESTAMPTZ,
+ operator_id BIGINT,
+ operator_name TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, cancel_id)
+);
+COMMENT ON TABLE billiards_ods.ods_assistant_cancel_log IS 'Source: 鍔╂暀搴熼櫎.json -> data.abolitionAssistants';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.tenant_id IS 'ingest context; tenant id not explicitly exported in abolitionAssistants';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.site_id IS 'source: abolitionAssistants.siteId; store id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.cancel_id IS 'source: abolitionAssistants.id; abolish record id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.ledger_id IS 'not present; reserved for related ledger id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.assistant_id IS 'not present in export; assistant name only in payload';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.order_trade_no IS 'not present in export; reserved for order number';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.table_id IS 'source: abolitionAssistants.tableId; table id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.table_area_id IS 'source: abolitionAssistants.tableAreaId; table area id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.table_area_name IS 'source: abolitionAssistants.tableArea; table area name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.table_name IS 'source: abolitionAssistants.tableName; table name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.assistant_on IS 'source: abolitionAssistants.assistantOn; number of assistants on duty';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.pd_charge_minutes IS 'source: abolitionAssistants.pdChargeMinutes; charged minutes';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.assistant_abolish_amount IS 'source: abolitionAssistants.assistantAbolishAmount; abolish amount';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.reason IS 'source: abolitionAssistants.trashReason; abolish reason';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.cancel_time IS 'source: abolitionAssistants.createTime; abolish time';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.operator_id IS 'not present in export; reserved for operator id';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.operator_name IS 'not present in export; reserved for operator name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.ods_assistant_cancel_log.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ package_id BIGINT NOT NULL,
+ package_name TEXT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ platform_code TEXT,
+ status TEXT,
+ face_price NUMERIC(18,2),
+ settle_price NUMERIC(18,2),
+ selling_price NUMERIC(18,2),
+ duration INT,
+ valid_from DATE,
+ valid_to DATE,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ is_enabled BOOLEAN,
+ is_delete BOOLEAN,
+ package_type TEXT,
+ usable_count INT,
+ creator_name TEXT,
+ tenant_table_area_id BIGINT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, package_id)
+);
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '鏉ユ簮锛氬洟璐椁?json -> data.packageCouponList锛涘洟璐?骞冲彴鍒稿畾涔?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '婧愬瓧娈?id/package_id锛涘椁愬畾涔塈D';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '婧愬瓧娈?package_name锛涘椁愬悕绉?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '婧愬瓧娈?table_area_id锛涢€傜敤鍖哄煙ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '婧愬瓧娈?table_area_name锛涢€傜敤鍖哄煙鍚嶇О';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.platform_code IS '婧愬瓧娈?groupon_type/system_group_type锛涘钩鍙?鍒告笭閬撶爜';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.status IS '婧愬瓧娈?effective_status锛涚敓鏁堢姸鎬?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.face_price IS '婧愬瓧娈?coupon_money锛涘埜闈㈤';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.settle_price IS '婧愭暟鎹湭鍗曞垪锛涢鐣欑粨绠椾环';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '婧愬瓧娈?selling_price锛涘敭鍗栦环';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '婧愬瓧娈?duration锛涙椂闀匡紙绉掞級';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.valid_from IS '婧愬瓧娈?start_time锛涙湁鏁堟湡寮€濮?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.valid_to IS '婧愬瓧娈?end_time锛涙湁鏁堟湡缁撴潫';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '婧愬瓧娈?start_clock/add_start_clock锛涙瘡鏃ョ敓鏁堣捣鐐?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '婧愬瓧娈?end_clock/add_end_clock锛涙瘡鏃ュけ鏁堢粓鐐?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '婧愬瓧娈?is_enabled锛涙槸鍚﹀惎鐢?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '婧愬瓧娈?is_delete锛涢€昏緫鍒犻櫎鏍囪';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_type IS '婧愬瓧娈?type/system_group_type/group_type锛涘椁愮被鍨?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '婧愬瓧娈?usable_count锛涘彲鐢ㄦ鏁?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '婧愬瓧娈?creator_name锛涘垱寤轰汉';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '婧愬瓧娈?tenant_table_area_id锛涚鎴风骇鍖哄煙ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages_log (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ usage_id BIGINT NOT NULL,
+ package_id BIGINT,
+ coupon_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ status TEXT,
+ used_time TIMESTAMPTZ,
+ deduct_amount NUMERIC(18,2),
+ settle_price NUMERIC(18,2),
+ coupon_code TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, usage_id)
+);
+COMMENT ON TABLE billiards_ods.group_buy_packages_log IS '鏉ユ簮锛氬洟璐椁愭祦姘?json -> data.siteTableUseDetailsList锛涘洟璐埜鏍搁攢娴佹按';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.usage_id IS '婧愬瓧娈?id锛涙牳閿€娴佹按ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.package_id IS '婧愬瓧娈?promotion_coupon_id锛涘椁?鍒窱D';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.coupon_id IS '婧愬瓧娈?order_coupon_id/coupon_origin_id锛涘埜瀹炰緥ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.order_trade_no IS '婧愬瓧娈?order_trade_no锛涗笟鍔¤鍗曞彿';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.order_settle_id IS '婧愬瓧娈?order_settle_id锛涚粨绠楀崟ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.member_id IS '婧愭暟鎹湭缁欙紱棰勭暀浼氬憳ID';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.status IS '婧愬瓧娈?ledger_status锛涙祦姘寸姸鎬?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.used_time IS '婧愬瓧娈?create_time锛涙牳閿€鏃堕棿';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.deduct_amount IS '婧愬瓧娈?coupon_money锛涘埜鎶垫墸閲戦';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.settle_price IS '婧愬瓧娈?ledger_amount锛涙湰鏉℃槑缁嗙粨绠楅噾棰?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.coupon_code IS '婧愬瓧娈?coupon_code锛涘埜鐮?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.group_buy_packages_log.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_platform_coupon_log (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ coupon_id BIGINT NOT NULL,
+ platform_code TEXT,
+ verify_code TEXT,
+ coupon_code TEXT,
+ coupon_channel TEXT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ status TEXT,
+ used_time TIMESTAMPTZ,
+ deduct_amount NUMERIC(18,2),
+ settle_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, coupon_id)
+);
+COMMENT ON TABLE billiards_ods.ods_platform_coupon_log IS '鏉ユ簮锛氬钩鍙伴獙鍒歌褰?json锛涘钩鍙板埜鏍搁攢璁板綍';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.tenant_id IS '婧愬瓧娈?tenant_id锛涚鎴?鍝佺墝ID';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.site_id IS '婧愬瓧娈?site_id锛涢棬搴桰D';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.coupon_id IS '婧愬瓧娈?id锛涙牳閿€璁板綍ID';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.platform_code IS '婧愬瓧娈?groupon_type锛涘埜骞冲彴/娓犻亾缂栫爜';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.verify_code IS '婧愬瓧娈?verify_id锛涙牳閿€娴佹按鍙?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.coupon_code IS '婧愬瓧娈?coupon_code锛涘埜鐮?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.coupon_channel IS '婧愬瓧娈?coupon_channel锛涢攢鍞笭閬?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.order_trade_no IS '婧愬瓧娈?site_order_id锛涘叧鑱旇鍗曞彿';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.order_settle_id IS '婧愭暟鎹湭缁欙紱棰勭暀缁撶畻ID';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.member_id IS '婧愭暟鎹湭缁欙紱棰勭暀浼氬憳ID';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.status IS '婧愬瓧娈?use_status锛涙牳閿€鐘舵€?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.used_time IS '婧愬瓧娈?consume_time锛涙牳閿€鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.deduct_amount IS '婧愬瓧娈?coupon_money锛涙姷鎵i噾棰?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.settle_price IS '婧愬瓧娈?sale_price锛涚粨绠?閿€鍞环';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.coupon_money IS '婧愬瓧娈?coupon_money锛涘埜闈㈤';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.source_file IS '閲囬泦鍏冩暟鎹細婧愭枃浠惰矾寰?;
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.source_endpoint IS '閲囬泦鍏冩暟鎹細鏉ユ簮鎺ュ彛/绔偣';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.fetched_at IS '閲囬泦鍏冩暟鎹細鍏ユ箹鏃堕棿';
+COMMENT ON COLUMN billiards_ods.ods_platform_coupon_log.payload IS '鍘熷JSON鍏ㄩ噺瀛樻。锛屼究浜庨噸鏀?瀹¤';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ change_id BIGINT NOT NULL,
+ site_goods_id BIGINT,
+ goods_id BIGINT,
+ stock_type TEXT,
+ change_amount NUMERIC(18,2),
+ before_stock NUMERIC(18,2),
+ after_stock NUMERIC(18,2),
+ change_amount_alt NUMERIC(18,2),
+ before_stock_alt NUMERIC(18,2),
+ after_stock_alt NUMERIC(18,2),
+ change_type TEXT,
+ relate_id BIGINT,
+ unit TEXT,
+ price NUMERIC(18,2),
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ change_time TIMESTAMPTZ,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, change_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_inventory_stock (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ site_goods_id BIGINT NOT NULL,
+ goods_id BIGINT,
+ goods_name TEXT,
+ goods_unit TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ range_start_stock NUMERIC(18,2),
+ range_end_stock NUMERIC(18,2),
+ range_in NUMERIC(18,2),
+ range_out NUMERIC(18,2),
+ range_inventory NUMERIC(18,2),
+ range_sale NUMERIC(18,2),
+ range_sale_money NUMERIC(18,2),
+ current_stock NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ category_name TEXT,
+ snapshot_key TEXT NOT NULL DEFAULT 'default',
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, site_goods_id, snapshot_key)
+);
+COMMENT ON TABLE billiards_ods.ods_inventory_stock IS 'Source: 搴撳瓨姹囨€?json';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.tenant_id IS 'ingest context; tenant id not explicitly exported';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.site_id IS 'ingest context; site id not explicitly exported';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.site_goods_id IS 'source: 搴撳瓨姹囨€?siteGoodsId; site goods id';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.goods_id IS 'not present in export; reserved for tenant goods id';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.goods_name IS 'source: 搴撳瓨姹囨€?goodsName; goods name';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.goods_unit IS 'source: 搴撳瓨姹囨€?goodsUnit; unit';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.goods_category_id IS 'source: 搴撳瓨姹囨€?goodsCategoryId; category id';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.goods_second_category_id IS 'source: 搴撳瓨姹囨€?goodsCategorySecondId; second category id';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_start_stock IS 'source: 搴撳瓨姹囨€?rangeStartStock; period opening stock';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_end_stock IS 'source: 搴撳瓨姹囨€?rangeEndStock; period closing stock';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_in IS 'source: 搴撳瓨姹囨€?rangeIn; inbound qty during period';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_out IS 'source: 搴撳瓨姹囨€?rangeOut; outbound qty during period';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_inventory IS 'source: 搴撳瓨姹囨€?rangeInventory; inventory adjustments during period';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_sale IS 'source: 搴撳瓨姹囨€?rangeSale; sales qty during period';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.range_sale_money IS 'source: 搴撳瓨姹囨€?rangeSaleMoney; sales amount during period';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.current_stock IS 'source: 搴撳瓨姹囨€?currentStock; current stock';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.cost_price IS 'not present in export; reserved for cost price';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.category_name IS 'source: 搴撳瓨姹囨€?categoryName; category name';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.snapshot_key IS 'snapshot label (default ''default'') for periodic loads';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.ods_inventory_stock.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ order_settle_id BIGINT NOT NULL,
+ settle_relate_id BIGINT,
+ settle_name TEXT,
+ settle_type INT,
+ settle_status INT,
+ member_id BIGINT,
+ member_name TEXT,
+ member_phone TEXT,
+ table_id BIGINT,
+ consume_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ pay_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ is_activity BOOLEAN,
+ is_bind_member BOOLEAN,
+ is_first BOOLEAN,
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ payment_method INT,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ can_be_revoked BOOLEAN,
+ serial_number TEXT,
+ sales_man_name TEXT,
+ sales_man_user_id BIGINT,
+ order_remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, order_settle_id)
+);
+COMMENT ON TABLE billiards_ods.settlement_records IS 'Source: 缁撹处璁板綍.json -> data.settleList[].settleList';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenant_id IS 'source: settleList.tenantId; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.settlement_records.site_id IS 'source: settleList.siteId; store id';
+COMMENT ON COLUMN billiards_ods.settlement_records.order_settle_id IS 'source: settleList.id; settlement record id';
+COMMENT ON COLUMN billiards_ods.settlement_records.settle_relate_id IS 'source: settleList.settleRelateId; related business/order id';
+COMMENT ON COLUMN billiards_ods.settlement_records.settle_name IS 'source: settleList.settleName; settlement name';
+COMMENT ON COLUMN billiards_ods.settlement_records.settle_type IS 'source: settleList.settleType; settlement type enum';
+COMMENT ON COLUMN billiards_ods.settlement_records.settle_status IS 'source: settleList.settleStatus; settlement status';
+COMMENT ON COLUMN billiards_ods.settlement_records.member_id IS 'source: settleList.memberId; member id';
+COMMENT ON COLUMN billiards_ods.settlement_records.member_name IS 'source: settleList.memberName; member name';
+COMMENT ON COLUMN billiards_ods.settlement_records.member_phone IS 'source: settleList.memberPhone; member phone';
+COMMENT ON COLUMN billiards_ods.settlement_records.table_id IS 'source: settleList.tableId; table id';
+COMMENT ON COLUMN billiards_ods.settlement_records.consume_money IS 'source: settleList.consumeMoney; total consumption amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.table_charge_money IS 'source: settleList.tableChargeMoney; table fee amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.goods_money IS 'source: settleList.goodsMoney; goods amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.service_money IS 'source: settleList.serviceMoney; service amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistant_pd_money IS 'source: settleList.assistantPdMoney; assistant accompany amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistant_cx_money IS 'source: settleList.assistantCxMoney; assistant promotion amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.pay_amount IS 'source: settleList.payAmount; payment amount (settled)';
+COMMENT ON COLUMN billiards_ods.settlement_records.cash_amount IS 'source: settleList.cashAmount; cash payment amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.online_amount IS 'source: settleList.onlineAmount; online payment amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.point_amount IS 'source: settleList.pointAmount; amount credited to card/points';
+COMMENT ON COLUMN billiards_ods.settlement_records.coupon_amount IS 'source: settleList.couponAmount; coupon deduction';
+COMMENT ON COLUMN billiards_ods.settlement_records.card_amount IS 'source: settleList.cardAmount; member card amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.balance_amount IS 'source: settleList.balanceAmount; balance payment amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.refund_amount IS 'source: settleList.refundAmount; refund amount on this settlement';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepay_money IS 'source: settleList.prepayMoney; prepayment amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjust_amount IS 'source: settleList.adjustAmount; adjustment amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.rounding_amount IS 'source: settleList.roundingAmount; rounding write-off amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.member_discount_amount IS 'source: settleList.memberDiscountAmount; member discount amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.coupon_sale_amount IS 'source: settleList.couponSaleAmount; coupon sale amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.goods_promotion_money IS 'source: settleList.goodsPromotionMoney; goods promotion deduction';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistant_promotion_money IS 'source: settleList.assistantPromotionMoney; assistant promotion deduction';
+COMMENT ON COLUMN billiards_ods.settlement_records.point_discount_price IS 'source: settleList.pointDiscountPrice; points discount amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.point_discount_cost IS 'source: settleList.pointDiscountCost; cost of points discount';
+COMMENT ON COLUMN billiards_ods.settlement_records.real_goods_money IS 'source: settleList.realGoodsMoney; real goods amount after discount';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistant_manual_discount IS 'source: settleList.assistantManualDiscount; manual assistant discount';
+COMMENT ON COLUMN billiards_ods.settlement_records.all_coupon_discount IS 'source: settleList.allCouponDiscount; total coupon discount';
+COMMENT ON COLUMN billiards_ods.settlement_records.is_use_coupon IS 'source: settleList.isUseCoupon; whether coupon used';
+COMMENT ON COLUMN billiards_ods.settlement_records.is_use_discount IS 'source: settleList.isUseDiscount; whether discount used';
+COMMENT ON COLUMN billiards_ods.settlement_records.is_activity IS 'source: settleList.isActivity; whether activity applied';
+COMMENT ON COLUMN billiards_ods.settlement_records.is_bind_member IS 'source: settleList.isBindMember; whether member bound';
+COMMENT ON COLUMN billiards_ods.settlement_records.is_first IS 'source: settleList.isFirst; whether first order flag';
+COMMENT ON COLUMN billiards_ods.settlement_records.recharge_card_amount IS 'source: settleList.rechargeCardAmount; recharge card amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.gift_card_amount IS 'source: settleList.giftCardAmount; gift card amount';
+COMMENT ON COLUMN billiards_ods.settlement_records.payment_method IS 'source: settleList.paymentMethod; payment method code';
+COMMENT ON COLUMN billiards_ods.settlement_records.create_time IS 'source: settleList.createTime; creation time';
+COMMENT ON COLUMN billiards_ods.settlement_records.pay_time IS 'source: settleList.payTime; pay time';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoke_order_id IS 'source: settleList.revokeOrderId; revoke order id';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoke_order_name IS 'source: settleList.revokeOrderName; revoke order name';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoke_time IS 'source: settleList.revokeTime; revoke time';
+COMMENT ON COLUMN billiards_ods.settlement_records.can_be_revoked IS 'source: settleList.canBeRevoked; flag whether revocable';
+COMMENT ON COLUMN billiards_ods.settlement_records.serial_number IS 'source: settleList.serialNumber; receipt serial number';
+COMMENT ON COLUMN billiards_ods.settlement_records.sales_man_name IS 'source: settleList.salesManName; sales person name';
+COMMENT ON COLUMN billiards_ods.settlement_records.sales_man_user_id IS 'source: settleList.salesManUserId; sales person user id';
+COMMENT ON COLUMN billiards_ods.settlement_records.order_remark IS 'source: settleList.orderRemark; order remark';
+COMMENT ON COLUMN billiards_ods.settlement_records.operator_id IS 'source: settleList.operatorId; operator id';
+COMMENT ON COLUMN billiards_ods.settlement_records.operator_name IS 'source: settleList.operatorName; operator name';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_goods_category (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ category_id BIGINT NOT NULL,
+ category_name TEXT,
+ parent_id BIGINT,
+ level_no INT,
+ status TEXT,
+ remark TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, category_id)
+);
+COMMENT ON TABLE billiards_ods.ods_goods_category IS 'Source: 搴撳瓨鍙樺寲璁板綍2.json -> data.goodsCategoryList';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.tenant_id IS 'source: goodsCategoryList.tenant_id; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.site_id IS 'ingest context; site id not explicitly exported';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.category_id IS 'source: goodsCategoryList.id; category id';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.category_name IS 'source: goodsCategoryList.category_name; category name';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.parent_id IS 'source: goodsCategoryList.pid; parent category id';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.level_no IS 'not present; reserved for category level';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.status IS 'source: goodsCategoryList.is_warehousing/open_salesman; category status flags';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.remark IS 'source: goodsCategoryList.alias_name/business_name; remark/alias';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.ods_goods_category.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ pay_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ pay_method_code TEXT,
+ pay_method_name TEXT,
+ pay_status INT,
+ pay_amount NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ online_pay_channel TEXT,
+ transaction_id TEXT,
+ operator_id BIGINT,
+ remark TEXT,
+ relate_type TEXT,
+ relate_id BIGINT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, pay_id)
+);
+COMMENT ON TABLE billiards_ods.payment_transactions IS 'Source: 鏀粯璁板綍.json';
+COMMENT ON COLUMN billiards_ods.payment_transactions.tenant_id IS 'ingest context; tenant id not explicitly exported';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS 'source: 鏀粯璁板綍.site_id; store id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_id IS 'source: 鏀粯璁板綍.id; payment record id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.order_trade_no IS 'not present in export; reserved for business order number';
+COMMENT ON COLUMN billiards_ods.payment_transactions.order_settle_id IS 'not present; reserved for settlement id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.member_id IS 'not present; reserved for member id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_method_code IS 'source: 鏀粯璁板綍.payment_method; payment method enum';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_method_name IS 'not present; reserved for payment method name';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS 'source: 鏀粯璁板綍.pay_status; payment status';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS 'source: 鏀粯璁板綍.pay_amount; paid amount';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS 'source: 鏀粯璁板綍.pay_time; payment time';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS 'source: 鏀粯璁板綍.online_pay_channel; online channel code';
+COMMENT ON COLUMN billiards_ods.payment_transactions.transaction_id IS 'not present in export; reserved for channel transaction id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.operator_id IS 'not present; reserved for operator id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.remark IS 'not present; reserved for remark';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS 'source: 鏀粯璁板綍.relate_type; related business type';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS 'source: 鏀粯璁板綍.relate_id; related business id';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ refund_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ is_revoke BOOLEAN,
+ is_delete BOOLEAN,
+ online_pay_channel TEXT,
+ pay_method_code TEXT,
+ refund_amount NUMERIC(18,2),
+ refund_time TIMESTAMPTZ,
+ action_type INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ member_card_id BIGINT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ online_pay_type INT,
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ check_status INT,
+ channel_fee NUMERIC(18,2),
+ relate_type TEXT,
+ relate_id BIGINT,
+ status TEXT,
+ reason TEXT,
+ related_payment_id BIGINT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, refund_id)
+);
+COMMENT ON TABLE billiards_ods.refund_transactions IS 'Source: 閫€娆捐褰?json';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS 'source: 閫€娆捐褰?tenant_id; tenant/brand id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS 'source: 閫€娆捐褰?site_id; store id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_id IS 'source: 閫€娆捐褰?id; refund record id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.order_trade_no IS 'not present in export; reserved for order number';
+COMMENT ON COLUMN billiards_ods.refund_transactions.order_settle_id IS 'not present; reserved for settlement id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS 'source: 閫€娆捐褰?member_id; member id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS 'source: 閫€娆捐褰?pay_sn; payment serial number';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS 'source: 閫€娆捐褰?pay_amount; paid amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS 'source: 閫€娆捐褰?pay_status; status code';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS 'source: 閫€娆捐褰?is_revoke; revoke flag';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS 'source: 閫€娆捐褰?is_delete; logical delete flag';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS 'source: 閫€娆捐褰?online_pay_channel; online pay channel';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_method_code IS 'source: 閫€娆捐褰?payment_method; payment method enum';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS 'source: 閫€娆捐褰?refund_amount; refund amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_time IS 'source: 閫€娆捐褰?pay_time; refund time';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS 'source: 閫€娆捐褰?action_type; action type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS 'source: 閫€娆捐褰?pay_terminal; pay terminal';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS 'source: 閫€娆捐褰?pay_config_id; pay config id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS 'source: 閫€娆捐褰?cashier_point_id; cashier point id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS 'source: 閫€娆捐褰?operator_id; operator id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS 'source: 閫€娆捐褰?member_card_id; member card id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS 'source: 閫€娆捐褰?balance_frozen_amount; frozen balance amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS 'source: 閫€娆捐褰?card_frozen_amount; frozen card amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS 'source: 閫€娆捐褰?round_amount; rounding/write-off amount';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS 'source: 閫€娆捐褰?online_pay_type; online refund type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS 'source: 閫€娆捐褰?channel_payer_id; channel payer id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS 'source: 閫€娆捐褰?channel_pay_no; channel transaction id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS 'source: 閫€娆捐褰?check_status; audit status';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS 'source: 閫€娆捐褰?channel_fee; channel fee';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS 'source: 閫€娆捐褰?relate_type; related business type';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS 'source: 閫€娆捐褰?relate_id; related business id';
+COMMENT ON COLUMN billiards_ods.refund_transactions.status IS 'alias for pay_status/is_delete to track row status';
+COMMENT ON COLUMN billiards_ods.refund_transactions.reason IS 'not present in export; reserved for refund reason';
+COMMENT ON COLUMN billiards_ods.refund_transactions.related_payment_id IS 'not present; reserved for linking to original payment';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS 'raw JSON payload for replay/debug';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.ods_order_receipt_detail (
+ tenant_id BIGINT,
+ site_id BIGINT NOT NULL,
+ order_settle_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_number TEXT,
+ settle_type INT,
+ receipt_no TEXT,
+ receipt_time TIMESTAMPTZ,
+ total_amount NUMERIC(18,2),
+ discount_amount NUMERIC(18,2),
+ final_amount NUMERIC(18,2),
+ actual_payment NUMERIC(18,2),
+ ledger_amount NUMERIC(18,2),
+ member_offer_amount NUMERIC(18,2),
+ delivery_fee NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ payment_method INT,
+ pay_time TIMESTAMPTZ,
+ member_id BIGINT,
+ order_remark TEXT,
+ cashier_name TEXT,
+ ticket_remark TEXT,
+ ticket_custom_content TEXT,
+ voucher_money NUMERIC(18,2),
+ reward_name TEXT,
+ consume_money NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ member_deduct_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ delivery_address TEXT,
+ snapshot_raw JSONB,
+ member_snapshot JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL,
+ PRIMARY KEY (site_id, order_settle_id)
+);
+COMMENT ON TABLE billiards_ods.ods_order_receipt_detail IS 'Source: 灏忕エ璇︽儏.json -> data.data (order detail)';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.order_settle_id IS 'source: orderSettleId; settlement id';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.order_trade_no IS 'not present in export; reserved for order number';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.order_settle_number IS 'source: orderSettleNumber; ticket/settlement number';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.settle_type IS 'source: settleType; settlement type enum';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.receipt_no IS 'not present in export; reserved for printed receipt number';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.receipt_time IS 'source: payTime; receipt/pay time';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.total_amount IS 'source: ledgerAmount; total amount before discounts';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.discount_amount IS 'derived from couponAmount/memberOfferAmount/pointDiscountPrice in payload; total discounts';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.final_amount IS 'source: consumeMoney; amount after discounts before payment';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.actual_payment IS 'source: actualPayment; amount actually paid';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.ledger_amount IS 'source: ledgerAmount; aggregated ledger amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.member_offer_amount IS 'source: memberOfferAmount; member discount amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.delivery_fee IS 'source: deliveryFee; delivery fee';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.adjust_amount IS 'source: adjustAmount; manual adjustment';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.payment_method IS 'source: paymentMethod; payment method code';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.pay_time IS 'source: payTime; payment time';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.member_id IS 'not present; memberProfile lacks id (only name/phone/point)';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.order_remark IS 'source: orderRemark; order remark';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.cashier_name IS 'source: cashierName; cashier name';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.ticket_remark IS 'source: ticketRemark; ticket remark';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.ticket_custom_content IS 'source: ticketCustomContent; custom print content';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.voucher_money IS 'source: voucherMoney; voucher amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.reward_name IS 'source: rewardName; reward description';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.consume_money IS 'source: consumeMoney; consumption amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.refund_amount IS 'source: refundAmount; refund amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.balance_amount IS 'source: balanceAmount or payMemberBalance; balance payment amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.coupon_amount IS 'source: couponAmount; coupon deduction amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.member_deduct_amount IS 'source: memberDeductAmount; member deduction amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.prepay_money IS 'source: prepayMoney; prepaid amount';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.delivery_address IS 'source: deliveryAddress; delivery address';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.snapshot_raw IS 'source: orderItem (table/goods/coupon ledgers); full nested detail JSON';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.member_snapshot IS 'source: memberProfile; member snapshot JSON';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.source_file IS 'ingest metadata: source file path';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.source_endpoint IS 'ingest metadata: API or endpoint name';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.fetched_at IS 'ingest metadata: load timestamp';
+COMMENT ON COLUMN billiards_ods.ods_order_receipt_detail.payload IS 'raw JSON payload for replay/debug';
+
+-- ---------- DWD Dimensions ----------
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_tenant (
+ tenant_id BIGINT PRIMARY KEY,
+ tenant_name TEXT,
+ short_name TEXT,
+ status TEXT,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_site (
+ site_id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_code TEXT,
+ site_name TEXT,
+ city TEXT,
+ region TEXT,
+ status TEXT,
+ open_date DATE,
+ close_date DATE,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_member_card_type (
+ card_type_id BIGINT PRIMARY KEY,
+ card_type_name TEXT,
+ discount_rate NUMERIC(8,4),
+ description TEXT,
+ remark TEXT
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_product_category (
+ category_id BIGINT PRIMARY KEY,
+ category_name TEXT,
+ parent_id BIGINT,
+ level_no INT,
+ status TEXT,
+ remark TEXT
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_product (
+ goods_id BIGINT PRIMARY KEY,
+ goods_name TEXT,
+ goods_code TEXT,
+ category_id BIGINT REFERENCES billiards_dwd.dim_product_category (category_id),
+ category_name TEXT,
+ unit TEXT,
+ default_price NUMERIC(18,2),
+ status TEXT,
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_table (
+ table_id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ table_code TEXT,
+ table_name TEXT,
+ table_type TEXT,
+ area_name TEXT,
+ status TEXT,
+ created_time TIMESTAMPTZ,
+ updated_time TIMESTAMPTZ
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_assistant_team (
+ team_id BIGINT PRIMARY KEY,
+ team_name TEXT,
+ remark TEXT,
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_assistant (
+ assistant_id BIGINT PRIMARY KEY,
+ assistant_name TEXT,
+ mobile TEXT,
+ team_id BIGINT REFERENCES billiards_dwd.dim_assistant_team (team_id),
+ status TEXT,
+ hired_date DATE,
+ left_date DATE,
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_pay_method (
+ pay_method_code TEXT PRIMARY KEY,
+ pay_method_name TEXT,
+ is_stored_value BOOLEAN DEFAULT FALSE,
+ status TEXT,
+ updated_at TIMESTAMPTZ DEFAULT now()
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_order_assist_type (
+ assist_type_code TEXT PRIMARY KEY,
+ assist_type_name TEXT,
+ description TEXT
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_coupon_platform (
+ platform_code TEXT PRIMARY KEY,
+ platform_name TEXT,
+ description TEXT
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_date (
+ date_key DATE PRIMARY KEY,
+ year_no INT,
+ month_no INT,
+ day_no INT,
+ week_no INT,
+ day_of_week INT,
+ month_name TEXT
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.dim_member (
+ site_id BIGINT,
+ member_id BIGINT,
+ tenant_id BIGINT,
+ member_name TEXT,
+ nickname TEXT,
+ gender TEXT,
+ birthday DATE,
+ mobile TEXT,
+ member_type_id BIGINT REFERENCES billiards_dwd.dim_member_card_type (card_type_id),
+ member_type_name TEXT,
+ status TEXT,
+ register_time TIMESTAMPTZ,
+ valid_from DATE,
+ valid_to DATE,
+ last_visit_time TIMESTAMPTZ,
+ balance NUMERIC(18,2),
+ total_recharge_amount NUMERIC(18,2),
+ total_consumed_amount NUMERIC(18,2),
+ wechat_id TEXT,
+ alipay_id TEXT,
+ remark TEXT,
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, member_id)
+);
+
+-- ---------- DWD Facts ----------
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_sale_item (
+ site_id BIGINT NOT NULL,
+ sale_item_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ goods_id BIGINT REFERENCES billiards_dwd.dim_product (goods_id),
+ category_id BIGINT REFERENCES billiards_dwd.dim_product_category (category_id),
+ quantity NUMERIC(18,4),
+ original_amount NUMERIC(18,2),
+ discount_amount NUMERIC(18,2),
+ final_amount NUMERIC(18,2),
+ is_gift BOOLEAN DEFAULT FALSE,
+ sale_time TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, sale_item_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_table_usage (
+ site_id BIGINT NOT NULL,
+ ledger_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ table_id BIGINT REFERENCES billiards_dwd.dim_table (table_id),
+ member_id BIGINT,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ duration_minutes INT,
+ original_table_fee NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ manual_discount_amount NUMERIC(18,2),
+ final_table_fee NUMERIC(18,2),
+ is_canceled BOOLEAN DEFAULT FALSE,
+ cancel_time TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, ledger_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_assistant_service (
+ site_id BIGINT NOT NULL,
+ ledger_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ assistant_id BIGINT REFERENCES billiards_dwd.dim_assistant (assistant_id),
+ assist_type_code TEXT REFERENCES billiards_dwd.dim_order_assist_type (assist_type_code),
+ member_id BIGINT,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ duration_minutes INT,
+ original_fee NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ manual_discount_amount NUMERIC(18,2),
+ final_fee NUMERIC(18,2),
+ is_canceled BOOLEAN DEFAULT FALSE,
+ cancel_time TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, ledger_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_coupon_usage (
+ site_id BIGINT NOT NULL,
+ coupon_id BIGINT NOT NULL,
+ package_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ platform_code TEXT REFERENCES billiards_dwd.dim_coupon_platform (platform_code),
+ status TEXT,
+ deduct_amount NUMERIC(18,2),
+ settle_price NUMERIC(18,2),
+ used_time TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, coupon_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_payment (
+ site_id BIGINT NOT NULL,
+ pay_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
+ pay_amount NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ relate_type TEXT,
+ relate_id BIGINT,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, pay_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_refund (
+ site_id BIGINT NOT NULL,
+ refund_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ member_id BIGINT,
+ pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
+ refund_amount NUMERIC(18,2),
+ refund_time TIMESTAMPTZ,
+ status TEXT,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, refund_id)
+);
+
+CREATE TABLE IF NOT EXISTS billiards_dwd.fact_balance_change (
+ site_id BIGINT NOT NULL,
+ change_id BIGINT NOT NULL,
+ member_id BIGINT,
+ change_type INT,
+ relate_type TEXT,
+ relate_id BIGINT,
+ pay_method_code TEXT REFERENCES billiards_dwd.dim_pay_method (pay_method_code),
+ change_amount NUMERIC(18,2),
+ balance_before NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ change_time TIMESTAMPTZ,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, change_id)
+);
+
+-- ---------- DWS (serving layers) ----------
+
+CREATE TABLE IF NOT EXISTS billiards_dws.dws_order_summary (
+ site_id BIGINT NOT NULL,
+ order_settle_id BIGINT NOT NULL,
+ order_trade_no TEXT,
+ order_date DATE,
+ tenant_id BIGINT,
+ member_id BIGINT,
+ member_flag BOOLEAN DEFAULT FALSE,
+ recharge_order_flag BOOLEAN DEFAULT FALSE,
+ item_count INT,
+ total_item_quantity NUMERIC(18,4),
+ table_fee_amount NUMERIC(18,2),
+ assistant_service_amount NUMERIC(18,2),
+ goods_amount NUMERIC(18,2),
+ group_amount NUMERIC(18,2),
+ total_coupon_deduction NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ manual_discount_amount NUMERIC(18,2),
+ order_original_amount NUMERIC(18,2),
+ order_final_amount NUMERIC(18,2),
+ stored_card_deduct NUMERIC(18,2),
+ external_paid_amount NUMERIC(18,2),
+ total_paid_amount NUMERIC(18,2),
+ book_table_flow NUMERIC(18,2),
+ book_assistant_flow NUMERIC(18,2),
+ book_goods_flow NUMERIC(18,2),
+ book_group_flow NUMERIC(18,2),
+ book_order_flow NUMERIC(18,2),
+ order_effective_consume_cash NUMERIC(18,2),
+ order_effective_recharge_cash NUMERIC(18,2),
+ order_effective_flow NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ net_income NUMERIC(18,2),
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ PRIMARY KEY (site_id, order_settle_id)
+);
+
+-- ---------- etl_admin (scheduler, cursor, run tracking) ----------
+CREATE SCHEMA IF NOT EXISTS etl_admin;
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_task (
+ task_id BIGSERIAL PRIMARY KEY,
+ task_code TEXT NOT NULL,
+ store_id BIGINT NOT NULL,
+ enabled BOOLEAN DEFAULT TRUE,
+ cursor_field TEXT,
+ window_minutes_default INT DEFAULT 30,
+ overlap_seconds INT DEFAULT 120,
+ page_size INT DEFAULT 200,
+ retry_max INT DEFAULT 3,
+ params JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_code, store_id)
+);
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_cursor (
+ cursor_id BIGSERIAL PRIMARY KEY,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ last_start TIMESTAMPTZ,
+ last_end TIMESTAMPTZ,
+ last_id BIGINT,
+ last_run_id BIGINT,
+ extra JSONB DEFAULT '{}'::jsonb,
+ created_at TIMESTAMPTZ DEFAULT now(),
+ updated_at TIMESTAMPTZ DEFAULT now(),
+ UNIQUE (task_id, store_id)
+);
+
+CREATE TABLE IF NOT EXISTS etl_admin.etl_run (
+ run_id BIGSERIAL PRIMARY KEY,
+ run_uuid TEXT NOT NULL,
+ task_id BIGINT NOT NULL REFERENCES etl_admin.etl_task(task_id) ON DELETE CASCADE,
+ store_id BIGINT NOT NULL,
+ status TEXT NOT NULL,
+ started_at TIMESTAMPTZ DEFAULT now(),
+ ended_at TIMESTAMPTZ,
+ window_start TIMESTAMPTZ,
+ window_end TIMESTAMPTZ,
+ window_minutes INT,
+ overlap_seconds INT,
+ fetched_count INT DEFAULT 0,
+ loaded_count INT DEFAULT 0,
+ updated_count INT DEFAULT 0,
+ skipped_count INT DEFAULT 0,
+ error_count INT DEFAULT 0,
+ unknown_fields INT DEFAULT 0,
+ export_dir TEXT,
+ log_path TEXT,
+ request_params JSONB DEFAULT '{}'::jsonb,
+ manifest JSONB DEFAULT '{}'::jsonb,
+ error_message TEXT,
+ extra JSONB DEFAULT '{}'::jsonb
+);
+
+-- Default task registry seed (idempotent)
+INSERT INTO etl_admin.etl_task (task_code, store_id, enabled)
+VALUES
+ ('PRODUCTS', 2790685415443269, TRUE),
+ ('TABLES', 2790685415443269, TRUE),
+ ('MEMBERS', 2790685415443269, TRUE),
+ ('ASSISTANTS', 2790685415443269, TRUE),
+ ('PACKAGES_DEF', 2790685415443269, TRUE),
+ ('ORDERS', 2790685415443269, TRUE),
+ ('PAYMENTS', 2790685415443269, TRUE),
+ ('REFUNDS', 2790685415443269, TRUE),
+ ('COUPON_USAGE', 2790685415443269, TRUE),
+ ('INVENTORY_CHANGE', 2790685415443269, TRUE),
+ ('TOPUPS', 2790685415443269, TRUE),
+ ('TABLE_DISCOUNT', 2790685415443269, TRUE),
+ ('ASSISTANT_ABOLISH', 2790685415443269, TRUE),
+ ('LEDGER', 2790685415443269, TRUE),
+ ('TICKET_DWD', 2790685415443269, TRUE),
+ ('PAYMENTS_DWD', 2790685415443269, TRUE),
+ ('MEMBERS_DWD', 2790685415443269, TRUE),
+ ('MANUAL_INGEST', 2790685415443269, TRUE),
+ ('settlement_records', 2790685415443269, TRUE),
+ ('table_fee_transactions', 2790685415443269, TRUE),
+ ('assistant_service_records', 2790685415443269, TRUE),
+ ('assistant_cancellation_records', 2790685415443269, TRUE),
+ ('ODS_GOODS_LEDGER', 2790685415443269, TRUE),
+ ('ODS_PAYMENT', 2790685415443269, TRUE),
+ ('ODS_REFUND', 2790685415443269, TRUE),
+ ('platform_coupon_redemption_records', 2790685415443269, TRUE),
+ ('ODS_MEMBER', 2790685415443269, TRUE),
+ ('member_stored_value_cards', 2790685415443269, TRUE),
+ ('ODS_PACKAGE', 2790685415443269, TRUE),
+ ('ODS_INVENTORY_STOCK', 2790685415443269, TRUE),
+ ('goods_stock_movements', 2790685415443269, TRUE)
+ON CONFLICT (task_code, store_id) DO NOTHING;
+
diff --git a/etl_billiards/草稿.txt b/tmp/etl_billiards_misc/草稿.txt
similarity index 80%
rename from etl_billiards/草稿.txt
rename to tmp/etl_billiards_misc/草稿.txt
index a430af7..5d333cf 100644
--- a/etl_billiards/草稿.txt
+++ b/tmp/etl_billiards_misc/草稿.txt
@@ -1,5 +1,5 @@
-一个用于开发的示例目录:C:\dev\LLTQ\export\test-json-doc
+一个用于开发的示例目录:export/test-json-doc
我建议完全删除LLZQ-test数据库中名称是billiards_ods的Schema下全部表和内容。根据非球接口API.md文档重建表,表名
@@ -18,7 +18,7 @@
下面开始重建数据库的ODS。
-一个用于开发的示例目录:C:\dev\LLTQ\export\test-json-doc。是测试用的json数据,并且已经按照现行逻辑进行了重命名。对应.md是Json数据的分析。
+一个用于开发的示例目录:export/test-json-doc。是测试用的json数据,并且已经按照现行逻辑进行了重命名。对应.md是Json数据的分析。
用于数据库ODS层的构建和Python文件的编写。
我建议完全删除LLZQ-test数据库中名称是billiards_ods的Schema下全部表和内容。根据上述示例目录的json和md文档重建表,表名就按对应json文件名来,字段名就是json字段名。
我理解ODS层本来就说Json文件的数据库留档,我这么理解对么?
diff --git a/hebing.py b/tmp/hebing.py
similarity index 100%
rename from hebing.py
rename to tmp/hebing.py
diff --git a/tmp/recharge_only/recharge_settlements.json b/tmp/recharge_only/recharge_settlements.json
new file mode 100644
index 0000000..4356334
--- /dev/null
+++ b/tmp/recharge_only/recharge_settlements.json
@@ -0,0 +1,6899 @@
+[
+ {
+ "data": {
+ "total": 74,
+ "settleList": [
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2956757480820613,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-09 03:49:17",
+ "memberId": 2799207159990021,
+ "memberName": "邓飛",
+ "tenantMemberCardId": 2799216107980549,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13600009597",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2956757480443781,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-09 03:49:17",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2956721495543301,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-09 03:12:40",
+ "memberId": 2955204541320325,
+ "memberName": "胡先生",
+ "tenantMemberCardId": 2955204541615237,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18620043391",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2956721495166469,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-09 03:12:41",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2956701447835141,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-09 02:52:17",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2956701447507461,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-09 02:52:17",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955465501214917,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-08 05:55:01",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2955465500805317,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-08 05:55:01",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955205277092101,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-08 01:30:18",
+ "memberId": 2955204541320325,
+ "memberName": "胡先生",
+ "tenantMemberCardId": 2955204541615237,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18620043391",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2955205276682501,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-08 01:30:18",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955202288371845,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-08 01:27:15",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": -5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": -5000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值撤销",
+ "settleRelateId": 2955202288175237,
+ "settleStatus": 2,
+ "settleType": 7,
+ "payTime": "2025-11-08 01:27:15",
+ "roundingAmount": 0.0,
+ "paymentMethod": 1,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955171778824325,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-08 00:56:13",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": -10000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": -10000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值撤销",
+ "settleRelateId": 2955171778627717,
+ "settleStatus": 2,
+ "settleType": 7,
+ "payTime": "2025-11-08 00:56:13",
+ "roundingAmount": 0.0,
+ "paymentMethod": 1,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955153378510917,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-08 00:37:30",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": 10000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 10000.0,
+ "pointAmount": 10000.0,
+ "refundAmount": 10000.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2955153378117701,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-08 00:37:30",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955100358478085,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-07 23:43:34",
+ "memberId": 2799207124305669,
+ "memberName": "陈腾鑫",
+ "tenantMemberCardId": 2799215988246277,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "17817318218",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2955100358117637,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-07 23:43:34",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2955078217844933,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-07 23:21:03",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 5000.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2955078217484485,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-07 23:21:03",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2954877830662341,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-07 19:57:12",
+ "memberId": 2799212491392773,
+ "memberName": "蔡总",
+ "tenantMemberCardId": 2799219205424901,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15914338893",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2954877830301893,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-07 19:57:12",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2953951073797829,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-07 04:14:27",
+ "memberId": 2799207290996485,
+ "memberName": "陈先生",
+ "tenantMemberCardId": 2799216397240069,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15915782829",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2953951073437381,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-07 04:14:27",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2952293091821189,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-06 00:07:52",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2952293091444357,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-06 00:07:52",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2951951831107333,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-05 18:20:43",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2951951830763269,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-05 18:20:43",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2951082620324037,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-05 03:36:31",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2951082619291845,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-05 03:36:31",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2947940365815429,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-02 22:20:03",
+ "memberId": 2799207599212293,
+ "memberName": "小熊",
+ "tenantMemberCardId": 2799217260676869,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13927020145",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2947940364979845,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-02 22:20:03",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2946627178694789,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-02 00:04:12",
+ "memberId": 2820625955784965,
+ "memberName": "江先生",
+ "tenantMemberCardId": 2820628725778629,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18819484838",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2946627178154117,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-02 00:04:12",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2946587840219269,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-01 23:24:11",
+ "memberId": 2799207599212293,
+ "memberName": "小熊",
+ "tenantMemberCardId": 2799217260676869,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13927020145",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2946587839744133,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-01 23:24:11",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2945598741858373,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-01 06:38:01",
+ "memberId": 2799207545685765,
+ "memberName": "李先生",
+ "tenantMemberCardId": 2799217107142405,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13128264000",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2945598741530693,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-01 06:38:02",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2945466615924805,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-01 04:23:37",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2945466615203909,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-01 04:23:37",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2945300260718597,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-11-01 01:34:24",
+ "memberId": 2945299652708293,
+ "memberName": "万先生",
+ "tenantMemberCardId": 2945299653003205,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13560399646",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2945300259784709,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-11-01 01:34:24",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2945086921656261,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-31 21:57:22",
+ "memberId": 2799207124305669,
+ "memberName": "陈腾鑫",
+ "tenantMemberCardId": 2799215988246277,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "17817318218",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2945086921279429,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-31 21:57:23",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2944744609302533,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-31 16:09:09",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": 4000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 4000.0,
+ "pointAmount": 4000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2944744608794629,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-31 16:09:09",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2944743805700165,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-31 16:08:20",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": -44000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": -44000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值撤销",
+ "settleRelateId": 2944743804553285,
+ "settleStatus": 2,
+ "settleType": 7,
+ "payTime": "2025-10-31 16:08:20",
+ "roundingAmount": 0.0,
+ "paymentMethod": 1,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2944743412713605,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-31 16:07:56",
+ "memberId": 2799207378798341,
+ "memberName": "羊",
+ "tenantMemberCardId": 2799216615507717,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18785445094",
+ "tableId": 0,
+ "consumeMoney": 44000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 44000.0,
+ "pointAmount": 44000.0,
+ "refundAmount": 44000.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2944743412123781,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-31 16:07:56",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2944055920218181,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-31 04:28:35",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2944055919824965,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-31 04:28:35",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2941311379247045,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-29 05:56:42",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2941311378837445,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-29 05:56:42",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2941006996098885,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-29 00:47:04",
+ "memberId": 2799207359858437,
+ "memberName": "罗先生",
+ "tenantMemberCardId": 2799218552833797,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13924036996",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2941006995771205,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-29 00:47:04",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2940962797752133,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-29 00:02:06",
+ "memberId": 2799207124305669,
+ "memberName": "陈腾鑫",
+ "tenantMemberCardId": 2799215988246277,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "17817318218",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2940962797326149,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-29 00:02:06",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2939340051942533,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-27 20:31:21",
+ "memberId": 2939339802315269,
+ "memberName": "方先生",
+ "tenantMemberCardId": 2939339802626565,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15360603185",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2939340051532933,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-27 20:31:21",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2937958490294789,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 5000.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-26 21:05:57",
+ "memberId": 2799209806071557,
+ "memberName": "陈德韩",
+ "tenantMemberCardId": 2799218773034757,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13431017864",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2937958489655813,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-26 21:05:58",
+ "roundingAmount": 0.0,
+ "paymentMethod": 2,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2936513767819653,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-25 20:36:19",
+ "memberId": 2799207370163973,
+ "memberName": "歌神",
+ "tenantMemberCardId": 2799216599402245,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18819262164",
+ "tableId": 0,
+ "consumeMoney": 2000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 2000.0,
+ "pointAmount": 2000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2936513766836613,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-25 20:36:19",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2936177402742341,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-25 14:54:09",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2936177402349125,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-25 14:54:09",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2935512880154181,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-25 03:38:09",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 10000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 10000.0,
+ "pointAmount": 10000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2935512879793733,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-25 03:38:09",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2935271550682758,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-24 23:32:40",
+ "memberId": 2935271033079557,
+ "memberName": "T",
+ "tenantMemberCardId": 2935271033390853,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18028579962",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2935271550289541,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-24 23:32:40",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2933648590063301,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-23 20:01:42",
+ "memberId": 2933647801731013,
+ "memberName": "桂先生",
+ "tenantMemberCardId": 2933647802009541,
+ "memberCardTypeName": "月卡",
+ "memberPhone": "16676777275",
+ "tableId": 0,
+ "consumeMoney": 985.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 985.0,
+ "pointAmount": 985.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2933648589670085,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-23 20:01:42",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2931088786392709,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-22 00:37:44",
+ "memberId": 2799207359858437,
+ "memberName": "罗先生",
+ "tenantMemberCardId": 2799218552833797,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13924036996",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2931088785819269,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-22 00:37:44",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2930700262180549,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-21 18:02:30",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 2000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 2000.0,
+ "pointAmount": 2000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2930700261770949,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-21 18:02:31",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2929261501040197,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-20 17:38:55",
+ "memberId": 2799212430657285,
+ "memberName": "黄先生",
+ "tenantMemberCardId": 2799219055920901,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13570163507",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2929261500696133,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-20 17:38:56",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2928709997495813,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-20 08:17:54",
+ "memberId": 2844990190242821,
+ "memberName": "叶总",
+ "tenantMemberCardId": 2844990190488581,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13711223287",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2928709997200901,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-20 08:17:54",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2928484764517765,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-20 04:28:47",
+ "memberId": 2799212499355397,
+ "memberName": "吕先生",
+ "tenantMemberCardId": 2799219220924165,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15559110663",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2928484764091781,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-20 04:28:47",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2928450397291909,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-20 03:53:50",
+ "memberId": 2844990190242821,
+ "memberName": "叶总",
+ "tenantMemberCardId": 2844990190488581,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13711223287",
+ "tableId": 0,
+ "consumeMoney": 700.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 700.0,
+ "pointAmount": 700.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2928450396915077,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-20 03:53:50",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2926790906103365,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-18 23:45:42",
+ "memberId": 2846153189592005,
+ "memberName": "黄先生",
+ "tenantMemberCardId": 2846153189837765,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15818822109",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2926790905775685,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-18 23:45:42",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2926696810563077,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-18 22:09:59",
+ "memberId": 2799207124305669,
+ "memberName": "陈腾鑫",
+ "tenantMemberCardId": 2799215988246277,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "17817318218",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2926696810169861,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-18 22:09:59",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2925404001666501,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-18 00:14:52",
+ "memberId": 2799207359858437,
+ "memberName": "罗先生",
+ "tenantMemberCardId": 2799218552833797,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13924036996",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2925404000994757,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-18 00:14:52",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2924166423692805,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-17 03:15:57",
+ "memberId": 2799207599212293,
+ "memberName": "小熊",
+ "tenantMemberCardId": 2799217260676869,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13927020145",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2924166423332357,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-17 03:15:57",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2924164846847365,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-17 03:14:20",
+ "memberId": 2820625955784965,
+ "memberName": "江先生",
+ "tenantMemberCardId": 2820628725778629,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18819484838",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2924164846519685,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-17 03:14:20",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2923680677430661,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-16 19:01:49",
+ "memberId": 2799207342704389,
+ "memberName": "叶先生",
+ "tenantMemberCardId": 2799216610576133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13826479539",
+ "tableId": 0,
+ "consumeMoney": 307.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 307.0,
+ "pointAmount": 307.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2923680676955525,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-16 19:01:49",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2922805984527877,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-16 04:12:02",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2922805984118277,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-16 04:12:02",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2922551421158789,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-15 23:53:05",
+ "memberId": 2799212499355397,
+ "memberName": "吕先生",
+ "tenantMemberCardId": 2799219220924165,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "15559110663",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2922551420749189,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-15 23:53:05",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2919713899613829,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-13 23:46:36",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2919713899269765,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-13 23:46:36",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2919691318627973,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 3000.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-13 23:23:38",
+ "memberId": 2919518015802181,
+ "memberName": "陶",
+ "tenantMemberCardId": 2919518016211781,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18924022151",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2919691318251141,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-13 23:23:38",
+ "roundingAmount": 0.0,
+ "paymentMethod": 2,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2919690721152517,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-13 23:23:01",
+ "memberId": 2919518015802181,
+ "memberName": "陶",
+ "tenantMemberCardId": 2919518016211781,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18924022151",
+ "tableId": 0,
+ "consumeMoney": -3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": -3000.0,
+ "pointAmount": 0.0,
+ "refundAmount": 0.0,
+ "settleName": "充值撤销",
+ "settleRelateId": 2919690720972293,
+ "settleStatus": 2,
+ "settleType": 7,
+ "payTime": "2025-10-13 23:23:01",
+ "roundingAmount": 0.0,
+ "paymentMethod": 1,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2919519810178693,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-13 20:29:10",
+ "memberId": 2919518015802181,
+ "memberName": "陶",
+ "tenantMemberCardId": 2919518016211781,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18924022151",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 3000.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2919519809605253,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-13 20:29:10",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2917921298729925,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-12 17:23:04",
+ "memberId": 2799207370163973,
+ "memberName": "歌神",
+ "tenantMemberCardId": 2799216599402245,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18819262164",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2917921298303941,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-12 17:23:05",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2917100006034181,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-12 03:27:37",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2917100005690117,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-12 03:27:37",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2916518262622981,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-11 17:35:50",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 10000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 10000.0,
+ "pointAmount": 10000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2916518262262533,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-11 17:35:50",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2915510025685701,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-11 00:30:12",
+ "memberId": 2799209768765189,
+ "memberName": "罗先生",
+ "tenantMemberCardId": 2799217471063813,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13922289222",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2915510025243333,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-11 00:30:12",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2915375205633029,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-10 22:13:03",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2915375205174277,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-10 22:13:03",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2913844390610501,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-09 20:15:50",
+ "memberId": 2799207124305669,
+ "memberName": "陈腾鑫",
+ "tenantMemberCardId": 2799215988246277,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "17817318218",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2913844390102597,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-09 20:15:50",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2913807879833221,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-09 19:38:41",
+ "memberId": 2848686922632133,
+ "memberName": "婉婉",
+ "tenantMemberCardId": 2848686922910661,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18345432742",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2913807879308933,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-09 19:38:41",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2912561032529349,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-08 22:30:20",
+ "memberId": 2799207287523077,
+ "memberName": "汪先生",
+ "tenantMemberCardId": 2799218289641221,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13925126339",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2912561032152517,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-08 22:30:20",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2911305097709189,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-08 01:12:43",
+ "memberId": 2799207580059397,
+ "memberName": "罗超",
+ "tenantMemberCardId": 2799219299469061,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13751780990",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2911305097201286,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-08 01:12:44",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 1,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2908450447476357,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-06 00:48:49",
+ "memberId": 2820625955784965,
+ "memberName": "江先生",
+ "tenantMemberCardId": 2820628725778629,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18819484838",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2908450447066757,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-06 00:48:50",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2908349322675589,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-05 23:05:57",
+ "memberId": 2799212845565701,
+ "memberName": "曾丹烨",
+ "tenantMemberCardId": 2799219999295237,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13922213242",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2908349322151301,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-05 23:05:57",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2907419840054661,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-05 07:20:26",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 5000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 5000.0,
+ "pointAmount": 5000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2907419839595909,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-05 07:20:26",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2907390916429189,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-05 06:51:01",
+ "memberId": 2799207342704389,
+ "memberName": "叶先生",
+ "tenantMemberCardId": 2799216610576133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13826479539",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2907390915954053,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-05 06:51:01",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2905666489108037,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-04 01:36:50",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2905666488649285,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-04 01:36:50",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2905552336307589,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-03 23:40:43",
+ "memberId": 2799207359858437,
+ "memberName": "罗先生",
+ "tenantMemberCardId": 2799218552833797,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13924036996",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2905552335750533,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-03 23:40:43",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2904235940514821,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-03 01:21:36",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2904235939908613,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-03 01:21:37",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2903676739456197,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-02 15:52:45",
+ "memberId": 2799207159990021,
+ "memberName": "邓飛",
+ "tenantMemberCardId": 2799216107980549,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13600009597",
+ "tableId": 0,
+ "consumeMoney": 1345.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1345.0,
+ "pointAmount": 1345.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2903676739013829,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-02 15:52:46",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2902997454785733,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-02 04:21:45",
+ "memberId": 2799207342704389,
+ "memberName": "叶先生",
+ "tenantMemberCardId": 2799216610576133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "13826479539",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2902997454326981,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-02 04:21:45",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2902496166988741,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-01 19:51:49",
+ "memberId": 2799207519176453,
+ "memberName": "夏",
+ "tenantMemberCardId": 2799217048848133,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "19120942851",
+ "tableId": 0,
+ "consumeMoney": 1000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 1000.0,
+ "pointAmount": 1000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2902496166398917,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-01 19:51:49",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ },
+ {
+ "siteProfile": {
+ "id": 2790685415443269,
+ "org_id": 2790684179467077,
+ "shop_name": "朗朗桌球",
+ "avatar": "https://oss.ficoo.vip/admin/hXcE4E_1752495052016.jpg",
+ "business_tel": "13316068642",
+ "full_address": "广东省广州市天河区丽阳街12号",
+ "address": "广东省广州市天河区天园街道朗朗桌球",
+ "longitude": 113.360321,
+ "latitude": 23.133629,
+ "tenant_site_region_id": 156440100,
+ "tenant_id": 2790683160709957,
+ "auto_light": 1,
+ "attendance_distance": 0,
+ "wifi_name": "",
+ "wifi_password": "",
+ "customer_service_qrcode": "",
+ "customer_service_wechat": "",
+ "fixed_pay_qrCode": "",
+ "prod_env": 1,
+ "light_status": 1,
+ "light_type": 0,
+ "site_type": 1,
+ "light_token": "",
+ "site_label": "A",
+ "attendance_enabled": 1,
+ "shop_status": 1
+ },
+ "settleList": {
+ "id": 2901346035322053,
+ "tenantId": 2790683160709957,
+ "siteId": 2790685415443269,
+ "siteName": "",
+ "balanceAmount": 0.0,
+ "cardAmount": 0.0,
+ "cashAmount": 0.0,
+ "couponAmount": 0.0,
+ "createTime": "2025-10-01 00:21:51",
+ "memberId": 2799207522600709,
+ "memberName": "轩哥",
+ "tenantMemberCardId": 2799217444914949,
+ "memberCardTypeName": "储值卡",
+ "memberPhone": "18826267530",
+ "tableId": 0,
+ "consumeMoney": 3000.0,
+ "onlineAmount": 0.0,
+ "operatorId": 2790687322443013,
+ "operatorName": "收银员:郑丽珊",
+ "revokeOrderId": 0,
+ "revokeOrderName": "",
+ "revokeTime": "0001-01-01 00:00:00",
+ "payAmount": 3000.0,
+ "pointAmount": 3000.0,
+ "refundAmount": 0.0,
+ "settleName": "充值订单",
+ "settleRelateId": 2901346034846917,
+ "settleStatus": 2,
+ "settleType": 5,
+ "payTime": "2025-10-01 00:21:51",
+ "roundingAmount": 0.0,
+ "paymentMethod": 4,
+ "adjustAmount": 0.0,
+ "assistantCxMoney": 0.0,
+ "assistantPdMoney": 0.0,
+ "couponSaleAmount": 0.0,
+ "memberDiscountAmount": 0.0,
+ "tableChargeMoney": 0.0,
+ "goodsMoney": 0.0,
+ "realGoodsMoney": 0.0,
+ "serviceMoney": 0.0,
+ "prepayMoney": 0.0,
+ "salesManName": "",
+ "orderRemark": "",
+ "salesManUserId": 0,
+ "canBeRevoked": false,
+ "pointDiscountPrice": 0.0,
+ "pointDiscountCost": 0.0,
+ "activityDiscount": 0.0,
+ "serialNumber": 0,
+ "assistantManualDiscount": 0.0,
+ "allCouponDiscount": 0.0,
+ "goodsPromotionMoney": 0.0,
+ "assistantPromotionMoney": 0.0,
+ "isUseCoupon": false,
+ "isUseDiscount": false,
+ "isActivity": false,
+ "isBindMember": false,
+ "isFirst": 2,
+ "rechargeCardAmount": 0,
+ "giftCardAmount": 0
+ }
+ }
+ ]
+ },
+ "code": 0
+ },
+ {
+ "data": {
+ "total": 74,
+ "settleList": []
+ },
+ "code": 0
+ }
+]
\ No newline at end of file
diff --git a/tmp/rewrite_schema_dwd_doc_comments.py b/tmp/rewrite_schema_dwd_doc_comments.py
new file mode 100644
index 0000000..16a4746
--- /dev/null
+++ b/tmp/rewrite_schema_dwd_doc_comments.py
@@ -0,0 +1,634 @@
+# -*- coding: utf-8 -*-
+import ast
+import json
+import re
+from collections import deque
+from pathlib import Path
+
+ROOT = Path(".")
+SQL_PATH = ROOT / "etl_billiards" / "database" / "schema_dwd_doc.sql"
+DOC_DIR = ROOT / "etl_billiards" / "export" / "test-json-doc"
+DWD_TASK_PATH = ROOT / "etl_billiards" / "tasks" / "dwd_load_task.py"
+
+SCD_COLS = {"scd2_start_time", "scd2_end_time", "scd2_is_current", "scd2_version"}
+
+SITEPROFILE_FIELD_PURPOSE = {
+ "id": "门店 ID,用于门店维度关联。",
+ "org_id": "组织/机构 ID,用于组织维度归属。",
+ "shop_name": "门店名称,用于展示与查询。",
+ "site_label": "门店标签(如 A/B 店),用于展示与分组。",
+ "full_address": "门店详细地址,用于展示与地理信息。",
+ "address": "门店地址简称/快照,用于展示。",
+ "longitude": "经度,用于定位与地图展示。",
+ "latitude": "纬度,用于定位与地图展示。",
+ "tenant_site_region_id": "租户下门店区域 ID,用于区域维度分析。",
+ "business_tel": "门店电话,用于联系信息展示。",
+ "site_type": "门店类型枚举,用于门店分类。",
+ "shop_status": "门店状态枚举,用于营业状态标识。",
+ "tenant_id": "租户/品牌 ID,用于商户维度过滤与关联。",
+ "auto_light": "是否启用自动灯控配置,用于门店设备策略。",
+ "attendance_enabled": "是否启用考勤功能,用于门店考勤配置。",
+ "attendance_distance": "考勤允许距离(米),用于考勤打卡限制。",
+ "prod_env": "环境标识(生产/测试),用于区分配置环境。",
+ "light_status": "灯控状态/开关,用于灯控设备管理。",
+ "light_type": "灯控类型,用于设备类型区分。",
+ "light_token": "灯控控制令牌,用于对接灯控服务。",
+ "avatar": "门店头像/图片 URL,用于展示。",
+ "wifi_name": "门店 WiFi 名称,用于展示与引导。",
+ "wifi_password": "门店 WiFi 密码,用于展示与引导。",
+ "customer_service_qrcode": "客服二维码 URL,用于引导联系。",
+ "customer_service_wechat": "客服微信号,用于引导联系。",
+ "fixed_pay_qrCode": "固定收款码(二维码)URL,用于收款引导。",
+ "create_time": "门店创建时间(快照字段)。",
+ "update_time": "门店更新时间(快照字段)。",
+}
+
+
+def _escape_sql(s: str) -> str:
+ return (s or "").replace("'", "''")
+
+
+def _first_sentence(text: str, max_len: int = 140) -> str:
+ s = re.sub(r"\s+", " ", (text or "").strip())
+ if not s:
+ return ""
+ parts = re.split(r"[。;;]\s*", s)
+ s = parts[0].strip() if parts else s
+ if len(s) > max_len:
+ s = s[: max_len - 1] + "…"
+ return s
+
+
+def normalize_key(s: str) -> str:
+ return re.sub(r"[_\-\s]", "", (s or "").lower())
+
+
+def snake_to_lower_camel(s: str) -> str:
+ parts = re.split(r"[_\-\s]+", s)
+ if not parts:
+ return s
+ first = parts[0].lower()
+ rest = "".join(p[:1].upper() + p[1:] for p in parts[1:] if p)
+ return first + rest
+
+
+def snake_to_upper_camel(s: str) -> str:
+ parts = re.split(r"[_\-\s]+", s)
+ return "".join(p[:1].upper() + p[1:] for p in parts if p)
+
+
+def find_key_in_record(record: dict, token: str) -> str | None:
+ if not isinstance(record, dict):
+ return None
+ if token in record:
+ return token
+ norm_to_key = {normalize_key(k): k for k in record.keys()}
+
+ candidates = [
+ token,
+ token.lower(),
+ token.upper(),
+ snake_to_lower_camel(token),
+ snake_to_upper_camel(token),
+ ]
+
+ # 常见变体:siteProfile/siteprofile
+ if normalize_key(token) == "siteprofile":
+ candidates.extend(["siteProfile", "siteprofile"])
+
+ for c in candidates:
+ nk = normalize_key(c)
+ if nk in norm_to_key:
+ return norm_to_key[nk]
+
+ return None
+
+
+def parse_dwd_task_mappings(path: Path):
+ mod = ast.parse(path.read_text(encoding="utf-8"))
+ table_map = None
+ fact_mappings = None
+
+ for node in mod.body:
+ if isinstance(node, ast.ClassDef) and node.name == "DwdLoadTask":
+ for stmt in node.body:
+ if isinstance(stmt, ast.Assign) and len(stmt.targets) == 1 and isinstance(stmt.targets[0], ast.Name):
+ name = stmt.targets[0].id
+ if name == "TABLE_MAP":
+ table_map = ast.literal_eval(stmt.value)
+ elif name == "FACT_MAPPINGS":
+ fact_mappings = ast.literal_eval(stmt.value)
+ if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name):
+ name = stmt.target.id
+ if name == "TABLE_MAP":
+ table_map = ast.literal_eval(stmt.value)
+ elif name == "FACT_MAPPINGS":
+ fact_mappings = ast.literal_eval(stmt.value)
+
+ if not isinstance(table_map, dict) or not isinstance(fact_mappings, dict):
+ raise RuntimeError("Failed to parse TABLE_MAP/FACT_MAPPINGS from dwd_load_task.py")
+
+ return table_map, fact_mappings
+
+
+def parse_columns_from_ddl(create_sql: str):
+ start = create_sql.find("(")
+ end = create_sql.rfind(")")
+ body = create_sql[start + 1 : end]
+
+ cols = []
+ for line in body.splitlines():
+ s = line.strip().rstrip(",")
+ if not s:
+ continue
+ if s.upper().startswith("PRIMARY KEY"):
+ continue
+ if s.upper().startswith("CONSTRAINT "):
+ continue
+ m = re.match(r"^([A-Za-z_][A-Za-z0-9_]*)\s+", s)
+ if not m:
+ continue
+ name = m.group(1)
+ if name.upper() in {"PRIMARY", "UNIQUE", "FOREIGN", "CHECK"}:
+ continue
+ cols.append(name.lower())
+ return cols
+
+
+def _find_best_record_list(data, required_norm_keys: set[str]):
+ best = None
+ best_score = -1.0
+ best_path: list[str] = []
+
+ q = deque([(data, 0, [])])
+ visited = 0
+
+ while q and visited < 25000:
+ node, depth, path = q.popleft()
+ visited += 1
+ if depth > 10:
+ continue
+
+ if isinstance(node, list):
+ if node and all(isinstance(x, dict) for x in node[:3]):
+ scores = []
+ for x in node[:5]:
+ keys_norm = {normalize_key(k) for k in x.keys()}
+ scores.append(len(keys_norm & required_norm_keys))
+ score = sum(scores) / max(1, len(scores))
+ if score > best_score:
+ best_score = score
+ best = node
+ best_path = path
+ for x in node[:10]:
+ q.append((x, depth + 1, path))
+ else:
+ for x in node[:120]:
+ q.append((x, depth + 1, path))
+ elif isinstance(node, dict):
+ for k, v in list(node.items())[:160]:
+ q.append((v, depth + 1, path + [str(k)]))
+
+ node_str = ".".join(best_path) if best_path else "$"
+ return best or [], node_str
+
+
+def _format_example(value, max_len: int = 120) -> str:
+ if value is None:
+ return "NULL"
+ if isinstance(value, bool):
+ return "true" if value else "false"
+ if isinstance(value, (int, float)):
+ return str(value)
+ if isinstance(value, str):
+ s = value.strip()
+ if len(s) > max_len:
+ s = s[: max_len - 1] + "…"
+ return s
+ if isinstance(value, dict):
+ keys = list(value)[:6]
+ mini = {k: value.get(k) for k in keys}
+ rendered = json.dumps(mini, ensure_ascii=False)
+ if len(value) > len(keys):
+ rendered = rendered[:-1] + ", …}"
+ if len(rendered) > max_len:
+ rendered = rendered[: max_len - 1] + "…"
+ return rendered
+ if isinstance(value, list):
+ if not value:
+ return "[]"
+ rendered = json.dumps(value[0], ensure_ascii=False)
+ if len(value) > 1:
+ rendered = f"[{rendered}, …] (len={len(value)})"
+ else:
+ rendered = f"[{rendered}]"
+ if len(rendered) > max_len:
+ rendered = rendered[: max_len - 1] + "…"
+ return rendered
+ s = str(value)
+ if len(s) > max_len:
+ s = s[: max_len - 1] + "…"
+ return s
+
+
+def _infer_purpose(table: str, col: str, json_path: str | None) -> str:
+ lcol = col.lower()
+
+ if lcol in SCD_COLS:
+ if lcol == "scd2_start_time":
+ return "SCD2 开始时间(版本生效起点),用于维度慢变追踪。"
+ if lcol == "scd2_end_time":
+ return "SCD2 结束时间(默认 9999-12-31 表示当前版本),用于维度慢变追踪。"
+ if lcol == "scd2_is_current":
+ return "SCD2 当前版本标记(1=当前,0=历史),用于筛选最新维度记录。"
+ if lcol == "scd2_version":
+ return "SCD2 版本号(自增),用于与时间段一起避免版本重叠。"
+
+ if json_path and json_path.startswith("siteProfile."):
+ sf = json_path.split(".", 1)[1]
+ return SITEPROFILE_FIELD_PURPOSE.get(sf, "门店快照字段,用于门店维度补充信息。")
+
+ if lcol.endswith("_id"):
+ return "标识类 ID 字段,用于关联/定位相关实体。"
+ if lcol.endswith("_time") or lcol.endswith("time") or lcol.endswith("_date"):
+ return "时间/日期字段,用于记录业务时间与统计口径对齐。"
+ if any(k in lcol for k in ["amount", "money", "fee", "price", "deduct", "cost", "balance"]):
+ return "金额字段,用于计费/结算/核算等金额计算。"
+ if any(k in lcol for k in ["count", "num", "number", "seconds", "qty", "quantity"]):
+ return "数量/时长字段,用于统计与计量。"
+ if lcol.endswith("_name") or lcol.endswith("name"):
+ return "名称字段,用于展示与辅助识别。"
+ if lcol.endswith("_status") or lcol == "status":
+ return "状态枚举字段,用于标识业务状态。"
+ if lcol.startswith("is_") or lcol.startswith("can_"):
+ return "布尔/开关字段,用于表示是否/可用性等业务开关。"
+
+ # 表级兜底
+ if table.startswith("dim_"):
+ return "维度字段,用于补充维度属性。"
+ return "明细字段,用于记录事实取值。"
+
+
+def _parse_json_extract(expr: str):
+ # e.g. siteprofile->>'org_id'
+ m = re.match(r"^([A-Za-z_][A-Za-z0-9_]*)\s*->>\s*'([^']+)'\s*$", expr)
+ if not m:
+ return None
+ base = m.group(1)
+ field = m.group(2)
+ if normalize_key(base) == "siteprofile":
+ base = "siteProfile"
+ return base, field
+
+
+def build_table_comment(table: str, source_ods: str | None, source_json_base: str | None) -> str:
+ table_l = table.lower()
+ if table_l.startswith("dim_"):
+ kind = "DWD 维度表"
+ else:
+ kind = "DWD 明细事实表"
+
+ extra = "扩展字段表" if table_l.endswith("_ex") else ""
+
+ if source_ods and source_json_base:
+ src = (
+ f"ODS 来源表:{source_ods}(对应 JSON:{source_json_base}.json;分析:{source_json_base}-Analysis.md)。"
+ f"装载/清洗逻辑参考:etl_billiards/tasks/dwd_load_task.py(DwdLoadTask)。"
+ )
+ else:
+ src = "来源:由 ODS 清洗装载生成(详见 DWD 装载任务)。"
+
+ return f"{kind}{('(' + extra + ')') if extra else ''}:{table_l}。{src}"
+
+
+def get_source_info(table_l: str, table_map: dict) -> tuple[str | None, str | None]:
+ key = f"billiards_dwd.{table_l}"
+ source_ods = table_map.get(key)
+ if not source_ods:
+ return None, None
+ json_base = source_ods.split(".")[-1]
+ return source_ods, json_base
+
+
+def build_column_mappings(table_l: str, cols: list[str], fact_mappings: dict) -> dict[str, tuple[str | None, str | None]]:
+ # return col -> (json_path, src_expr)
+ mapping_list = fact_mappings.get(f"billiards_dwd.{table_l}") or []
+ explicit = {dwd_col.lower(): src_expr for dwd_col, src_expr, _cast in mapping_list}
+ casts = {dwd_col.lower(): cast for dwd_col, _src_expr, cast in mapping_list}
+
+ out: dict[str, tuple[str | None, str | None]] = {}
+
+ for c in cols:
+ if c in SCD_COLS:
+ out[c] = (None, None)
+ continue
+
+ src_expr = explicit.get(c, c)
+ cast = casts.get(c)
+
+ json_path = None
+ parsed = _parse_json_extract(src_expr)
+ if parsed:
+ base, field = parsed
+ json_path = f"{base}.{field}"
+ else:
+ # derived: pay_date uses pay_time + cast date
+ if cast == "date":
+ json_path = src_expr
+ else:
+ json_path = src_expr
+
+ out[c] = (json_path, src_expr)
+
+ return out
+
+
+def load_json_records(json_base: str, required_norm_keys: set[str]):
+ json_path = DOC_DIR / f"{json_base}.json"
+ data = json.loads(json_path.read_text(encoding="utf-8"))
+ return _find_best_record_list(data, required_norm_keys)
+
+
+def pick_example_from_record(record: dict, json_path: str | None):
+ if not json_path:
+ return None
+ if json_path.startswith("siteProfile."):
+ base_key = find_key_in_record(record, "siteProfile")
+ base = record.get(base_key) if base_key else None
+ if isinstance(base, dict):
+ field = json_path.split(".", 1)[1]
+ return base.get(field)
+ return None
+
+ # plain key
+ key = find_key_in_record(record, json_path)
+ if key:
+ return record.get(key)
+ # fallback: try match by normalized name
+ nk = normalize_key(json_path)
+ for k in record.keys():
+ if normalize_key(k) == nk:
+ return record.get(k)
+ return None
+
+
+def resolve_json_field_display(records: list, json_path: str | None, cast: str | None = None) -> str:
+ if not json_path:
+ return "无"
+ if json_path.startswith("siteProfile."):
+ return json_path
+
+ actual_key = None
+ for r in records[:80]:
+ if not isinstance(r, dict):
+ continue
+ k = find_key_in_record(r, json_path)
+ if k:
+ actual_key = k
+ break
+
+ base = actual_key or json_path
+ if cast == "date":
+ return f"{base}(派生:DATE({base}))"
+ if cast == "boolean":
+ return f"{base}(派生:BOOLEAN({base}))"
+ if cast in {"numeric", "timestamptz"}:
+ return f"{base}(派生:CAST({base} AS {cast}))"
+ return base
+
+
+def resolve_ods_source_field(records: list, src_expr: str | None, cast: str | None = None) -> str:
+ if not src_expr:
+ return "无"
+
+ parsed = _parse_json_extract(src_expr)
+ if parsed:
+ base, field = parsed
+ # 统一大小写展示
+ if normalize_key(base) == "siteprofile":
+ base = "siteProfile"
+ return f"{base}.{field}"
+
+ # 直接字段:尽量输出 JSON 实际键名(大小写/驼峰)
+ actual = None
+ for r in records[:80]:
+ if not isinstance(r, dict):
+ continue
+ k = find_key_in_record(r, src_expr)
+ if k:
+ actual = k
+ break
+
+ base = actual or src_expr
+ if cast == "date":
+ return f"{base}(派生:DATE({base}))"
+ if cast == "boolean":
+ return f"{base}(派生:BOOLEAN({base}))"
+ if cast in {"numeric", "timestamptz"}:
+ return f"{base}(派生:CAST({base} AS {cast}))"
+ return base
+
+
+def resolve_json_field_triplet(
+ json_file: str | None,
+ record_node: str | None,
+ records: list,
+ json_path: str | None,
+ cast: str | None = None,
+) -> str:
+ if not json_file:
+ json_file = "无"
+ node = record_node or "$"
+
+ if not json_path:
+ return f"{json_file} - 无 - 无"
+
+ if json_path.startswith("siteProfile."):
+ base_key = None
+ field_key = None
+ for r in records[:80]:
+ if not isinstance(r, dict):
+ continue
+ base_key = find_key_in_record(r, "siteProfile")
+ if base_key:
+ base = r.get(base_key)
+ if isinstance(base, dict):
+ raw_field = json_path.split(".", 1)[1]
+ # 尽量匹配子字段大小写
+ if raw_field in base:
+ field_key = raw_field
+ else:
+ nk = normalize_key(raw_field)
+ for k in base.keys():
+ if normalize_key(k) == nk:
+ field_key = k
+ break
+ break
+ base_key = base_key or "siteProfile"
+ field_key = field_key or json_path.split(".", 1)[1]
+ node = f"{node}.{base_key}" if node else base_key
+ field = field_key
+ else:
+ actual = None
+ for r in records[:80]:
+ if isinstance(r, dict):
+ actual = find_key_in_record(r, json_path)
+ if actual:
+ break
+ field = actual or json_path
+
+ if cast == "date":
+ field = f"{field}(派生:DATE({field}))"
+ elif cast == "boolean":
+ field = f"{field}(派生:BOOLEAN({field}))"
+ elif cast in {"numeric", "timestamptz"}:
+ field = f"{field}(派生:CAST({field} AS {cast}))"
+
+ return f"{json_file} - {node} - {field}"
+
+
+def main():
+ table_map, fact_mappings = parse_dwd_task_mappings(DWD_TASK_PATH)
+
+ raw = SQL_PATH.read_text(encoding="utf-8", errors="replace")
+ newline = "\r\n" if "\r\n" in raw else "\n"
+
+ # strip all sql comments and existing COMMENT ON statements, incl. DO-block comment exec lines
+ kept_lines = []
+ for line in raw.splitlines(True):
+ if line.lstrip().startswith("--"):
+ continue
+ if re.match(r"^\s*COMMENT ON\s+(TABLE|COLUMN)\s+", line, re.I):
+ continue
+ if "COMMENT ON COLUMN" in line or "COMMENT ON TABLE" in line:
+ # remove legacy execute format lines too
+ continue
+ kept_lines.append(line)
+ clean = "".join(kept_lines)
+
+ create_re = re.compile(
+ r"(^\s*CREATE TABLE IF NOT EXISTS\s+(?P[A-Za-z0-9_]+)\s*\([\s\S]*?\)\s*;)",
+ re.M,
+ )
+
+ out_parts = []
+ last = 0
+ count_tables = 0
+
+ for m in create_re.finditer(clean):
+ stmt = m.group(1)
+ table = m.group("table").lower()
+
+ out_parts.append(clean[last : m.end()])
+
+ cols = parse_columns_from_ddl(stmt)
+
+ source_ods, json_base = get_source_info(table, table_map)
+
+ # derive required keys
+ required_norm = set()
+ col_map = build_column_mappings(table, cols, fact_mappings)
+ # cast map for json field display
+ cast_map = {
+ dwd_col.lower(): cast
+ for dwd_col, _src_expr, cast in (fact_mappings.get(f"billiards_dwd.{table}") or [])
+ }
+ src_expr_map = {
+ dwd_col.lower(): src_expr
+ for dwd_col, src_expr, _cast in (fact_mappings.get(f"billiards_dwd.{table}") or [])
+ }
+ for c, (jp, _src) in col_map.items():
+ if not jp:
+ continue
+ if jp.startswith("siteProfile."):
+ required_norm.add(normalize_key("siteProfile"))
+ else:
+ required_norm.add(normalize_key(jp))
+
+ records = []
+ record_node = "$"
+ if json_base and (DOC_DIR / f"{json_base}.json").exists():
+ try:
+ records, record_node = load_json_records(json_base, required_norm)
+ except Exception:
+ records = []
+ record_node = "$"
+
+ table_comment = build_table_comment(table, source_ods, json_base)
+ comment_lines = [f"COMMENT ON TABLE billiards_dwd.{table} IS '{_escape_sql(table_comment)}';"]
+
+ for c in cols:
+ jp, _src = col_map.get(c, (None, None))
+
+ if c in SCD_COLS:
+ if c == "scd2_start_time":
+ ex = "2025-11-10T00:00:00+08:00"
+ elif c == "scd2_end_time":
+ ex = "9999-12-31T00:00:00+00:00"
+ elif c == "scd2_is_current":
+ ex = "1"
+ else:
+ ex = "1"
+ json_field = "无 - DWD慢变元数据 - 无"
+ ods_src = "无(DWD慢变元数据)"
+ else:
+ # pick example from first records
+ ex_val = None
+ for r in records[:80]:
+ v = pick_example_from_record(r, jp)
+ if v not in (None, ""):
+ ex_val = v
+ break
+ ex = _format_example(ex_val)
+ json_field = resolve_json_field_triplet(
+ f"{json_base}.json" if json_base else None,
+ record_node,
+ records,
+ jp,
+ cast_map.get(c),
+ )
+ src_expr = src_expr_map.get(c, jp)
+ ods_src = resolve_ods_source_field(records, src_expr, cast_map.get(c))
+
+ purpose = _first_sentence(_infer_purpose(table, c, jp), 140)
+ func = purpose
+ if "用于" not in func:
+ func = "用于" + func.rstrip("。")
+
+ if source_ods:
+ ods_table_only = source_ods.split(".")[-1]
+ ods_src_display = f"{ods_table_only} - {ods_src}"
+ else:
+ ods_src_display = f"无 - {ods_src}"
+
+ comment = (
+ f"【说明】{purpose}。"
+ f" 【示例】{ex}({func})。"
+ f" 【ODS来源】{ods_src_display}。"
+ f" 【JSON字段】{json_field}。"
+ )
+ comment_lines.append(
+ f"COMMENT ON COLUMN billiards_dwd.{table}.{c} IS '{_escape_sql(comment)}';"
+ )
+
+ out_parts.append(newline + newline + (newline.join(comment_lines)) + newline + newline)
+ last = m.end()
+ count_tables += 1
+
+ out_parts.append(clean[last:])
+ result = "".join(out_parts)
+
+ # collapse extra blank lines
+ result = re.sub(r"(?:\r?\n){4,}", newline * 3, result)
+
+ backup = SQL_PATH.with_suffix(SQL_PATH.suffix + ".bak")
+ if not backup.exists():
+ backup.write_text(raw, encoding="utf-8")
+
+ SQL_PATH.write_text(result, encoding="utf-8")
+
+ print(f"Rewrote comments for {count_tables} tables: {SQL_PATH}")
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tmp/rewrite_schema_ods_doc_comments.py b/tmp/rewrite_schema_ods_doc_comments.py
new file mode 100644
index 0000000..db121ea
--- /dev/null
+++ b/tmp/rewrite_schema_ods_doc_comments.py
@@ -0,0 +1,560 @@
+# -*- coding: utf-8 -*-
+import json
+import re
+from pathlib import Path
+from collections import defaultdict
+
+SQL_PATH = Path("etl_billiards") / "database" / "schema_ODS_doc.sql"
+DOC_DIR = Path("etl_billiards") / "export" / "test-json-doc"
+
+TABLE_CN = {
+ "member_profiles": "会员档案/会员账户信息",
+ "member_balance_changes": "会员余额变更流水",
+ "member_stored_value_cards": "会员储值/卡券账户列表",
+ "recharge_settlements": "充值结算记录",
+ "settlement_records": "结账/结算记录",
+ "assistant_cancellation_records": "助教作废/取消记录",
+ "assistant_accounts_master": "助教档案主数据",
+ "assistant_service_records": "助教服务流水",
+ "site_tables_master": "门店桌台主数据",
+ "table_fee_discount_records": "台费折扣记录",
+ "table_fee_transactions": "台费流水",
+ "goods_stock_movements": "商品库存变动流水",
+ "stock_goods_category_tree": "商品分类树",
+ "goods_stock_summary": "商品库存汇总",
+ "payment_transactions": "支付流水",
+ "refund_transactions": "退款流水",
+ "platform_coupon_redemption_records": "平台券核销/使用记录",
+ "tenant_goods_master": "租户商品主数据",
+ "group_buy_packages": "团购套餐主数据",
+ "group_buy_redemption_records": "团购核销记录",
+ "settlement_ticket_details": "结算小票明细",
+ "store_goods_master": "门店商品主数据",
+ "store_goods_sales_records": "门店商品销售流水",
+}
+
+COMMON_FIELD_PURPOSE = {
+ "tenant_id": "租户/品牌 ID,用于商户维度过滤与关联。",
+ "site_id": "门店 ID,用于门店维度过滤与关联。",
+ "register_site_id": "会员注册门店 ID,用于归属门店维度关联。",
+ "site_name": "门店名称快照,用于直接展示。",
+ "id": "本表主键 ID,用于唯一标识一条记录。",
+ "system_member_id": "系统级会员 ID(跨门店/跨卡种统一到‘人’的维度)。",
+ "order_trade_no": "订单交易号,用于串联同一订单下的各类消费明细。",
+ "order_settle_id": "订单结算/结账主键,用于关联结算记录与小票明细。",
+ "order_pay_id": "关联支付流水的主键 ID,用于追溯支付明细。",
+ "point": "积分余额,用于记录会员积分取值。",
+ "growth_value": "成长值/成长积分,用于会员成长与等级评估。",
+ "referrer_member_id": "推荐人会员 ID,用于记录会员推荐/拉新关系。",
+ "create_time": "记录创建时间(业务侧产生时间)。",
+ "status": "状态枚举,用于标识记录当前业务状态。",
+ "user_status": "用户状态枚举,用于标识会员账户/用户可用状态。",
+ "is_delete": "逻辑删除标记(0=否,1=是)。",
+ "payload": "完整原始 JSON 记录快照,用于回溯与二次解析。",
+ "source_file": "ETL 元数据:原始导出文件名,用于数据追溯。",
+ "source_endpoint": "ETL 元数据:采集来源(接口/文件路径),用于数据追溯。",
+ "fetched_at": "ETL 元数据:采集/入库时间戳,用于口径对齐与增量处理。",
+}
+
+ETL_META_FIELDS = {"source_file", "source_endpoint", "fetched_at"}
+
+
+def _first_sentence(text: str, max_len: int = 120) -> str:
+ s = re.sub(r"\s+", " ", (text or "").strip())
+ if not s:
+ return ""
+ parts = re.split(r"[。;;]\s*", s)
+ s = parts[0].strip() if parts else s
+ if len(s) > max_len:
+ s = s[: max_len - 1] + "…"
+ return s
+
+
+def _escape_sql(s: str) -> str:
+ return (s or "").replace("'", "''")
+
+def normalize_key(s: str) -> str:
+ return re.sub(r"[_\-\s]", "", (s or "").lower())
+
+
+def snake_to_lower_camel(s: str) -> str:
+ parts = re.split(r"[_\-\s]+", s)
+ if not parts:
+ return s
+ first = parts[0].lower()
+ rest = "".join(p[:1].upper() + p[1:] for p in parts[1:] if p)
+ return first + rest
+
+
+def snake_to_upper_camel(s: str) -> str:
+ parts = re.split(r"[_\-\s]+", s)
+ return "".join(p[:1].upper() + p[1:] for p in parts if p)
+
+
+def find_key_in_record(record: dict, token: str) -> str | None:
+ if not isinstance(record, dict) or not token:
+ return None
+ if token in record:
+ return token
+ norm_to_key = {normalize_key(k): k for k in record.keys()}
+ candidates = [
+ token,
+ token.lower(),
+ token.upper(),
+ snake_to_lower_camel(token),
+ snake_to_upper_camel(token),
+ ]
+ for c in candidates:
+ nk = normalize_key(c)
+ if nk in norm_to_key:
+ return norm_to_key[nk]
+ return None
+
+
+def _infer_purpose(_table: str, col: str) -> str:
+ if col in COMMON_FIELD_PURPOSE:
+ return COMMON_FIELD_PURPOSE[col]
+
+ lower = col.lower()
+ if lower.endswith("_id"):
+ return "标识类 ID 字段,用于关联/定位相关实体。"
+ if lower.endswith("_time") or lower.endswith("time"):
+ return "时间字段,用于记录业务时间点/发生时间。"
+ if any(k in lower for k in ["amount", "money", "fee", "price", "deduct", "cost"]):
+ return "金额字段,用于计费/结算/分摊等金额计算。"
+ if any(k in lower for k in ["count", "num", "number", "seconds", "qty"]):
+ return "数量/时长字段,用于统计与计量。"
+ if lower.endswith("_name") or lower.endswith("name"):
+ return "名称字段,用于展示与辅助识别。"
+ if lower.endswith("_code") or lower.endswith("code"):
+ return "编码/枚举字段,用于表示类型、等级或业务枚举。"
+ if lower.startswith("is_") or lower.startswith("able_") or lower.startswith("can_"):
+ return "布尔/开关字段,用于表示权限、可用性或状态开关。"
+
+ return "来自 JSON 导出的原始字段,用于保留业务取值。"
+
+
+def _format_example(value, max_len: int = 120) -> str:
+ if value is None:
+ return "NULL"
+ if isinstance(value, bool):
+ return "true" if value else "false"
+ if isinstance(value, (int, float)):
+ return str(value)
+ if isinstance(value, str):
+ s = value.strip()
+ if len(s) > max_len:
+ s = s[: max_len - 1] + "…"
+ return s
+ if isinstance(value, list):
+ if not value:
+ return "[]"
+ sample = value[0]
+ rendered = json.dumps(sample, ensure_ascii=False)
+ if len(value) > 1:
+ rendered = f"[{rendered}, …] (len={len(value)})"
+ else:
+ rendered = f"[{rendered}]"
+ if len(rendered) > max_len:
+ rendered = rendered[: max_len - 1] + "…"
+ return rendered
+ if isinstance(value, dict):
+ keys = list(value)[:6]
+ mini = {k: value.get(k) for k in keys}
+ rendered = json.dumps(mini, ensure_ascii=False)
+ if len(value) > len(keys):
+ rendered = rendered[:-1] + ", …}"
+ if len(rendered) > max_len:
+ rendered = rendered[: max_len - 1] + "…"
+ return rendered
+ rendered = str(value)
+ if len(rendered) > max_len:
+ rendered = rendered[: max_len - 1] + "…"
+ return rendered
+
+
+def _find_best_record_list(data, columns):
+ cols = set(columns)
+ best = None
+ best_score = -1
+
+ queue = [(data, 0)]
+ visited = 0
+ while queue and visited < 20000:
+ node, depth = queue.pop(0)
+ visited += 1
+ if depth > 8:
+ continue
+ if isinstance(node, list):
+ if node and all(isinstance(x, dict) for x in node[:3]):
+ scores = []
+ for x in node[:5]:
+ scores.append(len(set(x.keys()) & cols))
+ score = sum(scores) / max(1, len(scores))
+ if score > best_score:
+ best_score = score
+ best = node
+ for x in node[:10]:
+ queue.append((x, depth + 1))
+ else:
+ for x in node[:50]:
+ queue.append((x, depth + 1))
+ elif isinstance(node, dict):
+ for v in list(node.values())[:80]:
+ queue.append((v, depth + 1))
+
+ return best
+
+
+def _find_best_record_list_and_node(data, columns):
+ cols = set(columns)
+ best = None
+ best_score = -1
+ best_path = []
+
+ queue = [(data, 0, [])]
+ visited = 0
+ while queue and visited < 25000:
+ node, depth, path = queue.pop(0)
+ visited += 1
+ if depth > 10:
+ continue
+
+ if isinstance(node, list):
+ if node and all(isinstance(x, dict) for x in node[:3]):
+ scores = []
+ for x in node[:5]:
+ scores.append(len(set(x.keys()) & cols))
+ score = sum(scores) / max(1, len(scores))
+ if score > best_score:
+ best_score = score
+ best = node
+ best_path = path
+ for x in node[:10]:
+ queue.append((x, depth + 1, path))
+ else:
+ for x in node[:80]:
+ queue.append((x, depth + 1, path))
+ elif isinstance(node, dict):
+ for k, v in list(node.items())[:120]:
+ queue.append((v, depth + 1, path + [str(k)]))
+
+ node_str = ".".join(best_path) if best_path else "$"
+ return best or [], node_str
+
+
+def _choose_examples(records, columns):
+ examples = {}
+ if not records:
+ return examples
+ for col in columns:
+ val = None
+ for r in records[:120]:
+ if isinstance(r, dict) and col in r and r[col] not in (None, ""):
+ val = r[col]
+ break
+ examples[col] = val
+ return examples
+
+
+def _extract_header_fields(line: str, columns_set):
+ s = line.strip()
+ if not s:
+ return []
+
+ # 支持 1. id / 1.1 siteProfile / 8. tenant_id
+ m = re.match(r"^\d+(?:\.\d+)*[\.)]?\s+(.+)$", s)
+ if m:
+ s = m.group(1).strip()
+
+ parts = re.split(r"\s*[/、,,]\s*", s)
+ fields = [p.strip() for p in parts if p.strip() in columns_set]
+
+ if not fields and s in columns_set:
+ fields = [s]
+
+ if fields and len(line) <= 120:
+ return fields
+ return []
+
+
+def _parse_field_purpose_from_block(block_lines):
+ lines = [l.rstrip() for l in block_lines]
+
+ def pick_after_label(labels):
+ for i, l in enumerate(lines):
+ for lab in labels:
+ if lab in l:
+ after = l.split(lab, 1)[1].strip()
+ if after:
+ return after
+ buf = []
+ j = i + 1
+ while j < len(lines) and not lines[j].strip():
+ j += 1
+ for k in range(j, len(lines)):
+ if not lines[k].strip():
+ break
+ if re.match(r"^[\w\u4e00-\u9fff]+[::]", lines[k].strip()):
+ break
+ buf.append(lines[k].strip())
+ if buf:
+ return " ".join(buf)
+ return ""
+
+ # 兼容「含义(结合其它文件):」「含义(推测):」等变体
+ picked = pick_after_label(["含义:", "含义:"])
+ if not picked:
+ for i, l in enumerate(lines):
+ s = l.strip()
+ m = re.match(r"^含义.*[::]\s*(.*)$", s)
+ if m:
+ after = m.group(1).strip()
+ if after:
+ picked = after
+ else:
+ buf = []
+ j = i + 1
+ while j < len(lines) and not lines[j].strip():
+ j += 1
+ for k in range(j, len(lines)):
+ if not lines[k].strip():
+ break
+ if re.match(r"^[\w\u4e00-\u9fff]+[::]", lines[k].strip()):
+ break
+ buf.append(lines[k].strip())
+ if buf:
+ picked = " ".join(buf)
+ break
+
+ if not picked:
+ picked = pick_after_label(["作用:", "作用:"])
+ if not picked:
+ for i, l in enumerate(lines):
+ s = l.strip()
+ m = re.match(r"^作用.*[::]\s*(.*)$", s)
+ if m:
+ after = m.group(1).strip()
+ if after:
+ picked = after
+ break
+
+ if not picked:
+ # 兜底:尽量避开“类型:/唯一值个数:”这类描述
+ for l in lines:
+ s = l.strip()
+ if not s:
+ continue
+ if any(
+ s.startswith(prefix)
+ for prefix in [
+ "类型:",
+ "非空:",
+ "唯一值",
+ "观测",
+ "特征",
+ "统计",
+ "分布",
+ "说明:",
+ "关联:",
+ "结构关系",
+ "和其它表",
+ "重复记录",
+ "全部为",
+ ]
+ ):
+ continue
+ picked = s
+ break
+
+ return _first_sentence(picked, 160)
+
+
+def _is_poor_purpose(purpose: str) -> bool:
+ s = (purpose or "").strip()
+ if not s:
+ return True
+ if s.endswith(":") or s.endswith(":"):
+ return True
+ if s.startswith("全部为"):
+ return True
+ if s.startswith("含义") and (":" in s or ":" in s) and len(s) <= 12:
+ return True
+ return False
+
+
+def parse_analysis(analysis_text: str, columns):
+ columns_set = set(columns)
+ blocks = defaultdict(list)
+
+ current_fields = []
+ buf = []
+
+ for raw in analysis_text.splitlines():
+ fields = _extract_header_fields(raw, columns_set)
+ if fields:
+ if current_fields and buf:
+ for f in current_fields:
+ blocks[f].extend(buf)
+ current_fields = fields
+ buf = []
+ else:
+ if current_fields:
+ buf.append(raw)
+
+ if current_fields and buf:
+ for f in current_fields:
+ blocks[f].extend(buf)
+
+ purposes = {}
+ for col in columns:
+ if col in blocks and blocks[col]:
+ p = _parse_field_purpose_from_block(blocks[col])
+ if p:
+ purposes[col] = p
+ return purposes
+
+
+def parse_columns_from_ddl(create_sql: str):
+ start = create_sql.find("(")
+ end = create_sql.rfind(")")
+ body = create_sql[start + 1 : end]
+
+ cols = []
+ for line in body.splitlines():
+ s = line.strip().rstrip(",")
+ if not s:
+ continue
+ if s.startswith(")"):
+ continue
+ if s.upper().startswith("CONSTRAINT "):
+ continue
+ m = re.match(r"^([A-Za-z_][A-Za-z0-9_]*)\s+", s)
+ if not m:
+ continue
+ name = m.group(1)
+ if name.upper() in {"PRIMARY", "UNIQUE", "FOREIGN", "CHECK"}:
+ continue
+ cols.append(name)
+ return cols
+
+
+def build_comment_block(table: str, columns, analysis_text: str, records):
+ # records_node: 由外部确定,避免这里重复遍历 JSON
+ records, records_node = records
+ purposes = parse_analysis(analysis_text, columns)
+ examples = _choose_examples(records, columns)
+
+ table_cn = TABLE_CN.get(table, table)
+
+ table_comment = (
+ f"ODS 原始明细表:{table_cn}。"
+ f"来源:etl_billiards/export/test-json-doc/{table}.json;分析:{table}-Analysis.md。"
+ f"字段以导出原样为主;ETL 补充 source_file/source_endpoint/fetched_at,并保留 payload 为原始记录快照。"
+ )
+
+ lines = []
+ lines.append(f"COMMENT ON TABLE billiards_ods.{table} IS '{_escape_sql(table_comment)}';")
+
+ for col in columns:
+ json_file = f"{table}.json"
+ if col in ETL_META_FIELDS:
+ json_field = f"{json_file} - ETL元数据 - 无"
+ elif col == "payload":
+ json_field = f"{json_file} - {records_node} - $"
+ else:
+ actual = None
+ for r in records[:50]:
+ if isinstance(r, dict):
+ actual = find_key_in_record(r, col)
+ if actual:
+ break
+ field_name = actual or col
+ json_field = f"{json_file} - {records_node} - {field_name}"
+
+ purpose = purposes.get(col) or _infer_purpose(table, col)
+ purpose = _first_sentence(purpose, 140) or _infer_purpose(table, col)
+ if _is_poor_purpose(purpose):
+ purpose = COMMON_FIELD_PURPOSE.get(col) or _infer_purpose(table, col)
+
+ if col in ETL_META_FIELDS:
+ if col == "source_file":
+ ex = f"{table}.json"
+ elif col == "source_endpoint":
+ ex = f"etl_billiards/export/test-json-doc/{table}.json"
+ else:
+ ex = "2025-11-10T00:00:00+08:00"
+ elif col == "payload":
+ ex = "{...}"
+ else:
+ ex = _format_example(examples.get(col))
+
+ func = purpose
+ if "用于" not in func:
+ func = "用于" + func.rstrip("。")
+
+ # ODS来源:表名-字段名(ODS自身字段);ETL补充字段标记
+ if col in ETL_META_FIELDS:
+ ods_src = f"{table} - {col}(ETL补充)"
+ else:
+ ods_src = f"{table} - {col}"
+
+ comment = (
+ f"【说明】{purpose}。"
+ f" 【示例】{ex}({func})。"
+ f" 【ODS来源】{ods_src}。"
+ f" 【JSON字段】{json_field}。"
+ )
+ lines.append(
+ f"COMMENT ON COLUMN billiards_ods.{table}.{col} IS '{_escape_sql(comment)}';"
+ )
+
+ return "\n".join(lines)
+
+
+text = SQL_PATH.read_text(encoding="utf-8")
+newline = "\r\n" if "\r\n" in text else "\n"
+
+kept = []
+for raw_line in text.splitlines(True):
+ stripped = raw_line.lstrip()
+ if stripped.startswith("--"):
+ continue
+ if re.match(r"^\s*COMMENT ON\s+(TABLE|COLUMN)\s+", raw_line):
+ continue
+ kept.append(raw_line)
+
+clean = "".join(kept)
+
+create_re = re.compile(
+ r"(CREATE TABLE IF NOT EXISTS\s+billiards_ods\.(?P[A-Za-z0-9_]+)\s*\([\s\S]*?\)\s*;)" ,
+ re.M,
+)
+
+out_parts = []
+last = 0
+count = 0
+for m in create_re.finditer(clean):
+ out_parts.append(clean[last : m.end()])
+ table = m.group("table")
+ create_sql = m.group(1)
+
+ cols = parse_columns_from_ddl(create_sql)
+ analysis_text = (DOC_DIR / f"{table}-Analysis.md").read_text(encoding="utf-8")
+ data = json.loads((DOC_DIR / f"{table}.json").read_text(encoding="utf-8"))
+ record_list, record_node = _find_best_record_list_and_node(data, cols)
+
+ out_parts.append(newline + newline + build_comment_block(table, cols, analysis_text, (record_list, record_node)) + newline + newline)
+ last = m.end()
+ count += 1
+
+out_parts.append(clean[last:])
+
+result = "".join(out_parts)
+result = re.sub(r"(?:\r?\n){4,}", newline * 3, result)
+
+backup = SQL_PATH.with_suffix(SQL_PATH.suffix + ".rewrite2.bak")
+backup.write_text(text, encoding="utf-8")
+SQL_PATH.write_text(result, encoding="utf-8")
+
+print(f"Rewrote comments for {count} tables. Backup: {backup}")
diff --git a/tmp/schema_ODS_doc copy.sql b/tmp/schema_ODS_doc copy.sql
new file mode 100644
index 0000000..d8a0408
--- /dev/null
+++ b/tmp/schema_ODS_doc copy.sql
@@ -0,0 +1,1886 @@
+-- 文件:schema_ODS_doc.sql
+-- 说明:ODS 层 DDL,表名与示例 JSON 前缀对应,用于本地回放/调试。
+-- 编码:UTF-8
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS '对应JSON字段:member_profiles.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_profiles-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '对应JSON字段:tenant_id,说明::,示例值及对应分析:租户/品牌 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '对应JSON字段:register_site_id,说明::,示例值及对应分析:会员的注册门店 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '对应JSON字段:site_name,说明::,示例值及对应分析:注册门店名称,属于冗余字段,用于直接展示。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '对应JSON字段:id,说明::,示例值及对应分析:这是“租户内会员账户”的主键 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '对应JSON字段:system_member_id,说明:(结合其它文件):,示例值及对应分析:这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明:类型:int,示例值及对应分析:唯一值个数:4';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '对应JSON字段:member_card_grade_name,说明::,示例值及对应分析:这是“会员卡种类/等级”的定义字段。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '对应JSON字段:mobile,说明::,示例值及对应分析:会员绑定的手机号码。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '对应JSON字段:nickname,说明::,示例值及对应分析:会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '对应JSON字段:point,说明::,示例值及对应分析:当前积分余额(这条会员账户的积分值)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '对应JSON字段:growth_value,说明:(按常见会员体系设计):,示例值及对应分析:成长值 / 经验值,用于会员等级晋升的累计指标。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '对应JSON字段:referrer_member_id,说明:(按命名推断):,示例值及对应分析:推荐人会员 ID,用于记录该会员是由哪位老会员推荐。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '对应JSON字段:status,说明:(按命名推断):,示例值及对应分析:帐户状态(偏“卡状态/档案状态”)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '对应JSON字段:user_status,说明:(结合行业惯例):,示例值及对应分析:用户账号状态(偏“用户逻辑”层面的状态)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '对应JSON字段:create_time,说明::,示例值及对应分析:会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '对应JSON字段:member_balance_changes.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '对应JSON字段:tenant_id,说明::租户/商户 ID,本数据中是固定值(同一品牌/商户)。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '对应JSON字段:site_id,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '对应JSON字段:register_site_id,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '对应JSON字段:registerSiteName,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '对应JSON字段:paySiteName,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '对应JSON字段:id,说明::余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::商户维度的会员 ID(租户内会员主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '对应JSON字段:tenant_member_card_id,说明::会员卡账户 ID,在租户内唯一标识某张卡。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '对应JSON字段:system_member_id,说明::系统级(全局)会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '对应JSON字段:memberName,说明::会员姓名或称呼(非昵称字段)。,示例值及对应分析:说明:例如“陈腾鑫”“胡先生”“江先生”等,多为中文姓名或带“先生”称呼。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '对应JSON字段:memberMobile,说明::会员手机号。,示例值及对应分析:说明:字符型存储,完整手机号,用来识别会员与联系客户。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '对应JSON字段:card_type_id,说明::卡种类型 ID,用于区分不同卡种。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '对应JSON字段:memberCardTypeName,说明::卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '对应JSON字段:account_data,说明::本次变动的金额(元),正数表示增加,负数表示减少。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '对应JSON字段:before,说明::本次变动前,该卡账户的余额(元)。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '对应JSON字段:after,说明::本次变动后,该卡账户的余额(元)。,示例值及对应分析:重要关系:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):与退款业务相关的金额字段,但在当前这份导出中实际未使用:,示例值及对应分析:可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '对应JSON字段:from_type,说明:(根据金额符号与 remark 综合推断):,示例值及对应分析:1:日常消费扣款';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '对应JSON字段:payment_method,说明:类型:int,枚举,示例值及对应分析:值分布:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '对应JSON字段:relate_id,说明:(推测):关联业务记录的 ID:,示例值及对应分析:例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '对应JSON字段:remark,说明::,示例值及对应分析:当为空时,说明这条变动没有额外备注说明。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '对应JSON字段:operator_id,说明::执行此次余额变更操作的员工 ID。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。,示例值及对应分析:9. 状态字段与标志';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标记:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '对应JSON字段:create_time,说明::本条余额变更记录的创建时间,通常接近交易发生时间。,示例值及对应分析:说明:可与订单、支付记录的时间做对齐,构造时序链路(但你现在不要求做时序分析,这里只说明结构)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '对应JSON字段:member_stored_value_cards.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,与其他 JSON 中 tenant_id 一致。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::当前商户(品牌/租户)中会员的主键 ID。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '对应JSON字段:system_member_id,说明::系统级会员 ID(跨门店统一主键)。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '对应JSON字段:register_site_id,说明::卡首次办理的门店 ID。,示例值及对应分析:对应门店的 site_id;本数据中所有卡都是在同一家门店开卡。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '对应JSON字段:site_name,说明::卡归属门店名称(视图中的展示字段)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '对应JSON字段:id,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明::卡等级/卡类代码,和下面两个名称字段一一对应。,示例值及对应分析:枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '对应JSON字段:member_card_grade_code_name,说明::卡等级/卡类名称。,示例值及对应分析:枚举值(与上面 code 一一对应):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '对应JSON字段:member_card_type_name,说明::卡类型名称,实际与 member_card_grade_code_name 一致。,示例值及对应分析:枚举值同上。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '对应JSON字段:member_name,说明::持卡会员姓名快照。,示例值及对应分析:特点:存在 null(20 张卡没有绑定会员名字)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '对应JSON字段:member_mobile,说明::持卡会员手机号快照。,示例值及对应分析:特点:与 member_name 对应,多数有值,少量为 null。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '对应JSON字段:card_type_id,说明::卡种 ID(定义“这是哪一种卡”)。,示例值及对应分析:枚举(按数据分布):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '对应JSON字段:card_no,说明:(推测):实体卡物理卡号/条码号。当前这批卡看起来全部为“无物理卡号”(可能是全部虚拟卡或卡号隐藏不导出)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '对应JSON字段:card_physics_type,说明::物理卡类型。,示例值及对应分析:当前数据:全部为 1。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '对应JSON字段:balance,说明::当前卡内余额(主要针对储值卡、部分券卡)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '对应JSON字段:denomination,说明:(推测):面额/初始储值额度。,示例值及对应分析:本页数据未填充此字段;可能在分类型卡(如次卡/券)中才有意义,或者另有配置表。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '对应JSON字段:table_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '对应JSON字段:goods_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '对应JSON字段:assistant_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '对应JSON字段:assistant_reward_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '对应JSON字段:table_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '对应JSON字段:assistant_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '对应JSON字段:coupon_discount,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '对应JSON字段:goods_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '对应JSON字段:assistant_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '对应JSON字段:table_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '对应JSON字段:goods_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '对应JSON字段:assistant_reward_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '对应JSON字段:table_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '对应JSON字段:assistant_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '对应JSON字段:goods_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '对应JSON字段:assistant_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '对应JSON字段:table_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '对应JSON字段:goods_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '对应JSON字段:coupon_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '对应JSON字段:assistant_reward_deduct_radio,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '对应JSON字段:tableCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '对应JSON字段:tableServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '对应JSON字段:goodsCarDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '对应JSON字段:goodsServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '对应JSON字段:assistantCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '对应JSON字段:assistantServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '对应JSON字段:assistantRewardCardDeduct,说明::助教奖励金方向扣款的配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '对应JSON字段:cardSettleDeduct,说明:已在扣卡规则部分说明,当前为 0。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '对应JSON字段:couponCardDeduct,说明::与卡绑定的“券额度扣除配置”。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '对应JSON字段:deliveryFeeDeduct,说明::配送费可否/多少从卡中抵扣,目前无业务发生。,示例值及对应分析:综合来看:本门店的卡片在“规则配置层”预留了大量细粒度控制字段,但目前实际使用只体现在“balance”和“可用范围”,折扣和具体扣卡规则基本都未启用(全部保持默认值 10 折、100%比例、0 扣款),真正扣款逻辑在交易流水中体现。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '对应JSON字段:use_scene,说明::卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。,示例值及对应分析:2. 会员信息与关联字段';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '对应JSON字段:able_cross_site,说明::是否允许跨店使用。,示例值及对应分析:1:可以跨门店使用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '对应JSON字段:is_allow_give,说明::是否允许转赠/转让给其他会员。,示例值及对应分析:0:不允许;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '对应JSON字段:is_allow_order_deduct,说明::是否允许在“订单层面统一扣款”。,示例值及对应分析:0:不允许(仅按项目扣卡);';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '对应JSON字段:bind_password,说明::卡绑定密码,用于消费或查询验证(目前未启用)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '对应JSON字段:goods_discount_range_type,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '对应JSON字段:tableAreaId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '对应JSON字段:effect_site_id,说明:(推测):卡片限定生效门店 ID。,示例值及对应分析:为 0 时,配合 able_cross_site=1,可解释为“所有门店可用”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '对应JSON字段:start_time,说明::卡片生效开始时间(有效期起始)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '对应JSON字段:end_time,说明::卡片有效期结束时间。,示例值及对应分析:start_time / end_time 组合就是卡的有效期。不同卡种有效期配置不同,如储值卡长效、月卡固定一个月等。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '对应JSON字段:disable_start_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '对应JSON字段:disable_end_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '对应JSON字段:last_consume_time,说明::最近一次消费时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '对应JSON字段:create_time,说明::卡片创建时间(开卡时间)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '对应JSON字段:status,说明:(推测):,示例值及对应分析:1:正常可用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '对应JSON字段:sort,说明::在前端展示或某些列表中的排序权重。,示例值及对应分析:具体取值分布不重要,主要反映展示优先级。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '对应JSON字段:tenantAvatar,说明::品牌头像 URL(未配置)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '对应JSON字段:tenantName,说明::租户/品牌名称(当前导出为空)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '对应JSON字段:pdAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '对应JSON字段:cxAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS '对应JSON字段:recharge_settlements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '对应JSON字段:id,说明::本条充值结算记录的主键 ID(唯一标识一条充值/撤销记录)。,示例值及对应分析:唯一性:74 条记录全部不同。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '对应JSON字段:tenantid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '对应JSON字段:siteid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '对应JSON字段:sitename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '对应JSON字段:balanceamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '对应JSON字段:cardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '对应JSON字段:cashamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '对应JSON字段:couponamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '对应JSON字段:createtime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '对应JSON字段:memberid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '对应JSON字段:membername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '对应JSON字段:memberphone,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '对应JSON字段:tableid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '对应JSON字段:consumemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '对应JSON字段:onlineamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '对应JSON字段:operatorid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '对应JSON字段:operatorname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '对应JSON字段:revokeordername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '对应JSON字段:revoketime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '对应JSON字段:payamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '对应JSON字段:pointamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '对应JSON字段:refundamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '对应JSON字段:settlename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '对应JSON字段:settlestatus,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '对应JSON字段:settletype,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '对应JSON字段:paytime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '对应JSON字段:roundingamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '对应JSON字段:adjustamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '对应JSON字段:servicemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '对应JSON字段:salesmanname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '对应JSON字段:orderremark,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '对应JSON字段:canberevoked,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '对应JSON字段:serialnumber,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '对应JSON字段:isusediscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '对应JSON字段:isactivity,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '对应JSON字段:isbindmember,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '对应JSON字段:isfirst,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS '对应JSON字段:settlement_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '对应JSON字段:id,说明::结账记录主键 ID(订单结算 ID)。,示例值及对应分析:结构关联:';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '对应JSON字段:tenantid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '对应JSON字段:siteid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '对应JSON字段:sitename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '对应JSON字段:balanceamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '对应JSON字段:cardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '对应JSON字段:cashamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '对应JSON字段:couponamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '对应JSON字段:createtime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '对应JSON字段:memberid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '对应JSON字段:membername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '对应JSON字段:memberphone,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '对应JSON字段:tableid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '对应JSON字段:consumemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '对应JSON字段:onlineamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '对应JSON字段:operatorid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '对应JSON字段:operatorname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '对应JSON字段:revokeordername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '对应JSON字段:revoketime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '对应JSON字段:payamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '对应JSON字段:pointamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '对应JSON字段:refundamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '对应JSON字段:settlename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '对应JSON字段:settlestatus,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '对应JSON字段:settletype,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '对应JSON字段:paytime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '对应JSON字段:roundingamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '对应JSON字段:adjustamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '对应JSON字段:servicemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '对应JSON字段:salesmanname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '对应JSON字段:orderremark,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '对应JSON字段:canberevoked,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '对应JSON字段:serialnumber,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '对应JSON字段:isusediscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '对应JSON字段:isactivity,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '对应JSON字段:isbindmember,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '对应JSON字段:isfirst,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS '对应JSON字段:assistant_cancellation_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '对应JSON字段:id,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '对应JSON字段:siteId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '对应JSON字段:assistantName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '对应JSON字段:assistantAbolishAmount,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '对应JSON字段:assistantOn,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '对应JSON字段:pdChargeMinutes,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '对应JSON字段:tableAreaId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '对应JSON字段:tableArea,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '对应JSON字段:tableId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '对应JSON字段:tableName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '对应JSON字段:trashReason,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '对应JSON字段:createTime,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS '对应JSON字段:assistant_accounts_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '对应JSON字段:id,说明::助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。,示例值及对应分析:作用:所有与助教相关的事实表(助教流水、助教排班等)都会通过这个 ID 关联到该维表。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '对应JSON字段:tenant_id,说明::品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。,示例值及对应分析:用途:多门店时用来区分不同商户。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '对应JSON字段:site_id,说明::门店 ID,对应本次数据的这家球房(朗朗桌球)。,示例值及对应分析:关联:与其它 JSON(台费流水、库存、销售等)中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '对应JSON字段:assistant_no,说明:(结合字段名推测):助教工号 / 编号,便于业务侧识别。,示例值及对应分析:关联:在“助教流水.json”中有 assistantNo,与此字段对应。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '对应JSON字段:nickname,说明::助教在前台展示的昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:用途:与真实姓名区分,用于顾客侧展示。如在助教流水中 nickname 就是这个值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '对应JSON字段:real_name,说明::助教真实姓名,如“何海婷”“梁婷婷”等。,示例值及对应分析:关联:在“助教流水.json”的 assistantName 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '对应JSON字段:mobile,说明::助教手机号,用于登录绑定、通知、钉钉同步等。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '对应JSON字段:team_id,说明::助教所属团队 ID。,示例值及对应分析:关联:在“助教流水.json”中 assistant_team_id 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '对应JSON字段:team_name,说明::团队名称,展示用,和 team_id 一一对应。,示例值及对应分析:group_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '对应JSON字段:level,说明:(结合“助教流水中的 assistant_level / levelName 推测”):,示例值及对应分析:8:助教管理/管理员(和流水里的 "助教管理" 对应)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '对应JSON字段:assistant_status,说明:(推测):账号启用状态:,示例值及对应分析:1:启用';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '对应JSON字段:work_status,说明::,示例值及对应分析:1:在岗/可排班';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '对应JSON字段:leave_status,说明:类型:int,枚举。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '对应JSON字段:entry_time,说明::入职时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '对应JSON字段:resign_time,说明::离职日期;使用“远未来日期”作为“未离职”的占位。,示例值及对应分析:entry_type';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '对应JSON字段:start_time,说明:(推测):当前配置生效的开始日期。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '对应JSON字段:end_time,说明::当前配置生效的结束日期(例如一个周期性的排班/合同周期)。,示例值及对应分析:last_table_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '对应JSON字段:create_time,说明::账号创建时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '对应JSON字段:update_time,说明::账号最近一次被修改的时间(例如修改等级、昵称等)。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '对应JSON字段:order_trade_no,说明:(推测):该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。,示例值及对应分析:9. 灯控、钉钉等系统集成相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '对应JSON字段:staff_id,说明:(推测):预留给“人事系统员工 ID”的字段,目前未接入或未启用。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '对应JSON字段:staff_profile_id,说明:(推测):人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。,示例值及对应分析:4. 等级、计费与薪资配置字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '对应JSON字段:system_role_id,说明:?????? assistant_accounts_master-Analysis.md,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '对应JSON字段:avatar,说明::助教头像地址。,示例值及对应分析:introduce';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '对应JSON字段:gender,说明:(结合常见约定与值分布推测):,示例值及对应分析:0:未填/保密';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '对应JSON字段:show_status,说明:(推测):前台展示状态:,示例值及对应分析:1:在助教选择界面展示。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '对应JSON字段:show_sort,说明::前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。,示例值及对应分析:online_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '对应JSON字段:sum_grade,说明::评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '对应JSON字段:get_grade_times,说明::累计被评分次数。,示例值及对应分析:charge_way';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '对应JSON字段:video_introduction_url,说明::助教个人视频介绍地址。,示例值及对应分析:height';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '对应JSON字段:user_id,说明:账号对应的用户 ID/员工 ID,用于跨表关联。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '对应JSON字段:height,说明:身高(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '对应JSON字段:weight,说明:体重(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '对应JSON字段:job_num,说明:工号/岗位编号,保留原始取值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '对应JSON字段:assistant_grade,说明:平均评分,通常 = sum_grade/get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '对应JSON字段:introduce,说明:个人简介/自我介绍,可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '对应JSON字段:group_id,说明:分组/自定义分组 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '对应JSON字段:group_name,说明:分组名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '对应JSON字段:shop_name,说明:门店名称冗余。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '对应JSON字段:charge_way,说明:收费方式枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '对应JSON字段:entry_type,说明:入职类型枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '对应JSON字段:allow_cx,说明:是否允许超休/冲销(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '对应JSON字段:is_guaranteed,说明:是否保底(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '对应JSON字段:salary_grant_enabled,说明:薪资发放/补贴开关,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '对应JSON字段:light_status,说明:灯控状态/模式,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '对应JSON字段:online_status,说明:在线状态标记(0/1等)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '对应JSON字段:is_delete,说明:逻辑删除标记(0=有效,1=删除)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '对应JSON字段:cx_unit_price,说明:超休单价/冲销单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '对应JSON字段:pd_unit_price,说明:排钟/点钟单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '对应JSON字段:last_table_id,说明:最近服务桌台 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '对应JSON字段:last_table_name,说明:最近服务桌台名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '对应JSON字段:person_org_id,说明:人员组织 ID/部门 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '对应JSON字段:serial_number,说明:序列号/排序号,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '对应JSON字段:is_team_leader,说明:是否组长(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '对应JSON字段:criticism_status,说明:处罚/警告状态标记,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '对应JSON字段:ding_talk_synced,说明:是否已同步钉钉(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '对应JSON字段:site_light_cfg_id,说明:门店灯控配置 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '对应JSON字段:light_equipment_id,说明:灯控设备 ID/硬件编号。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '对应JSON字段:entry_sign_status,说明:入职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '对应JSON字段:resign_sign_status,说明:离职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS '对应JSON字段:assistant_service_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '对应JSON字段:id,说明::本条助教流水记录的主键 ID(流水唯一标识)。,示例值及对应分析:作用:在系统内部唯一定位这一条助教服务记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID;你这份数据中是固定值(同一个商户)。,示例值及对应分析:关联:全库所有表都有,作为“商户维度”的过滤键。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本数据中指“朗朗桌球”这一家门店。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。,示例值及对应分析:作用:冗余门店信息,方便查看(而不是每次都联表看门店档案)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::订单结算 ID,相当于“结账单号”的内部主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,整个订单层面的编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '对应JSON字段:order_pay_id,说明::关联到“支付记录”的主键 ID。,示例值及对应分析:作用:可以和支付记录中的 id / relate_id 等字段对应,找到这条助教服务对应的支付流水。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '对应JSON字段:order_assistant_id,说明::订单中“助教项目明细”的内部 ID。,示例值及对应分析:作用:如果订单里有多条助教项目(比如换助教、多个时间段),此字段唯一标识这一条助教明细。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '对应JSON字段:order_assistant_type,说明:(推测):,示例值及对应分析:1:常规助教服务(主课/基础课)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '对应JSON字段:assistantName,说明::助教姓名,如“何海婷”“胡敏”等。,示例值及对应分析:备注:和助教账号档案里的 real_name 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '对应JSON字段:assistantNo,说明::助教编号,例如 "27"。,示例值及对应分析:关联:在助教账号表里也有 assistant_no 字段,对应工号/编号。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '对应JSON字段:assistant_level,说明::助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。,示例值及对应分析:备注:属于展示用的冗余字段。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '对应JSON字段:assistant_team_id,说明::当前这条助教服务所对应的“课程/技能名称”。,示例值及对应分析:当 order_assistant_type = 1 时,多为“基础课”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '对应JSON字段:nickname,说明::助教对外昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:说明:从数据看,这个 nickname 是“助教昵称”,不是顾客昵称(容易混淆)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '对应JSON字段:ledger_name,说明:?????? assistant_service_records-Analysis.md,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。,示例值及对应分析:目前未被实际使用。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。,示例值及对应分析:说明:从数据看,这个金额对应“按原价计费”的金额,未扣除各种优惠。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计时总秒数。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::助教服务 标准单价(通常是标价:每小时、每节课的单价)。,示例值及对应分析:特点:如 98.0、108.0、190.0 等。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):助教流水记录状态:,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账层面记录的开始时间。,示例值及对应分析:说明:与 start_use_time 在当前数据中完全一致,可以视为“计费起始时间”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账层面的结束时间。,示例值及对应分析:说明:与 last_use_time 一致,可以视为“计费结束时间”。对于 real_use_seconds = 0 的记录,开始和结束时间相同,说明只是预约/录入,并未实际服务。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '对应JSON字段:manual_discount_amount,说明::收银员手动给予的减免金额(人工改价)。,示例值及对应分析:当前导出时间段内暂未出现手动打折的情况。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员卡折扣产生的优惠金额。,示例值及对应分析:说明:尽管字段里是 0,但实际折扣可能已经体现在 projected_income 与 ledger_amount 的差额中,这里只是未单独拆出。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '对应JSON字段:service_money,说明:(推测):用于记录与助教结算的金额(平台预留的“成本/分成”字段)。,示例值及对应分析:当前数据中未启用这个机制,所以全为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '对应JSON字段:projected_income,说明::实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。,示例值及对应分析:从数据:projected_income 明显低于 ledger_amount,说明中间有折扣,但折扣的明细并不全由下面几个字段体现(很多是卡权益内生折扣)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '对应JSON字段:real_use_seconds,说明::实际使用时长(秒)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '对应JSON字段:income_seconds,说明::计费秒数 / 应计收入对应的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '对应JSON字段:start_use_time,说明::助教实际开始服务时间。,示例值及对应分析:特点:正常情况下与 ledger_start_time 相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '对应JSON字段:last_use_time,说明::最后一次使用(实际服务)时间。,示例值及对应分析:特点:正常结束时与 ledger_end_time 相同;如果服务还未真正开始或立即结束,开始/结束时间可能相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '对应JSON字段:create_time,说明::这条助教流水记录创建时间(一般接近结算/下单时间)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独订单:,示例值及对应分析:1:本助教服务作为单独订单结算(或单独拆项)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '对应JSON字段:is_trash,说明::是否已废除/作废:,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '对应JSON字段:trash_reason,说明::废除原因(文本说明),例如“顾客取消”“录入错误”等。,示例值及对应分析:当前数据为空字符串,说明当前导出时间段没有被废除的助教流水记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '对应JSON字段:trash_applicant_id,说明::提出废除申请的员工 ID(通常是操作员/管理员)。,示例值及对应分析:当前数据全为 0,因此短期内没有发生废除操作。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '对应JSON字段:trash_applicant_name,说明::废除申请人姓名。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入/结算这条助教服务的员工)。,示例值及对应分析:关联:可与员工/账号表对应(本次导出未单独给员工表,但其他 JSON 里多处出现该 ID)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,与 operator_id 一起使用,便于直接阅读。,示例值及对应分析:user_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '对应JSON字段:salesman_name,说明::关联的“营业员/销售员姓名”,用于提成归属。,示例值及对应分析:观测:本数据中多数为空字符串,说明助教流水没有配置单独的营业员。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:观测:多为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID。,示例值及对应分析:观测:多为 0,代表未指定。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '对应JSON字段:person_org_id,说明:同样在上文说明:助教所属人事组织 ID。,示例值及对应分析:9. 作废 / 废除相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '对应JSON字段:add_clock,说明:(推测):加钟秒数,即在原有预约/服务基础上临时追加的时长。,示例值及对应分析:说明:值均为 60 的倍数(分钟级加钟),如 600 秒=10 分钟。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '对应JSON字段:returns_clock,说明:(推测):退钟秒数(取消加钟或提前结束退回的时间)。,示例值及对应分析:当前数据里没有退钟场景,所以全为 0,但字段设计已经预留。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '对应JSON字段:composite_grade,说明::综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '对应JSON字段:composite_grade_time,说明:(推测):最近一次评价时间/综合评分更新时间。现在都是默认“无效时间”。,示例值及对应分析:3. 桌台 / 门店维度字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '对应JSON字段:skill_grade,说明:(推测):顾客对“技能表现”的评分(整数或打分等级)。,示例值及对应分析:当前数据中还未产生评分记录,所以都是默认值 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '对应JSON字段:service_grade,说明:(推测):顾客对“服务态度”的评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '对应JSON字段:sum_grade,说明::累计评分总和(可能用于计算平均分),当前为 0。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '对应JSON字段:grade_status,说明:(推测):评价状态,比如:,示例值及对应分析:1 = 未评价/正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '对应JSON字段:get_grade_times,说明::该条记录对应的评价次数(或该助教被评价次数快照)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '对应JSON字段:is_not_responding,说明:(推测):是否存在“爽约/未响应”情况:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '对应JSON字段:is_confirm,说明:(推测):确认状态,例如:,示例值及对应分析:1:待确认;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS '对应JSON字段:site_tables_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '对应JSON字段:id,说明::台桌主键 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '对应JSON字段:siteName,说明::门店名称快照,冗余字段,配合 site_id 使用。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master."appletQrCodeUrl" IS '对应JSON字段:appletQrCodeUrl,说明::小程序二维码 URL。 一般用于:,示例值及对应分析:打印二维码贴在台上,顾客扫码可呼叫服务、查看账单或发起线上预约;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '对应JSON字段:areaName,说明::区域名称,用于前台展示和区域维度管理。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '对应JSON字段:audit_status,说明:(结合命名惯例):,示例值及对应分析:2:已审核/已启用;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '对应JSON字段:charge_free,说明:(推测):,示例值及对应分析:0:正常计费;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '对应JSON字段:create_time,说明::台桌配置的创建时间或最近一次创建/复制时间。,示例值及对应分析:三、与其它 JSON 的字段级关联关系(结构视角)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '对应JSON字段:delay_lights_time,说明:(推测):台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。,示例值及对应分析:本门店未启用延迟关灯功能(全部为 0)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '对应JSON字段:is_online_reservation,说明:(结合值分布推断):,示例值及对应分析:1:允许线上预约(可在小程序/线上平台预约这张台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '对应JSON字段:is_rest_area,说明:(推测):,示例值及对应分析:0:正常计费区域;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '对应JSON字段:light_status,说明:(结合命名推断):,示例值及对应分析:该字段是台灯/灯光状态开关位:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '对应JSON字段:only_allow_groupon,说明:(结合命名推断):,示例值及对应分析:1:仅允许团购/券预约使用(团购专用台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '对应JSON字段:order_delay_time,说明:(推测):订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。,示例值及对应分析:本门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '对应JSON字段:self_table,说明:(推测):,示例值及对应分析:1:“本门店自有台”,非共享或外部配置;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '对应JSON字段:show_status,说明:(推测):,示例值及对应分析:1:正常在前台“开台列表”中展示;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店维度的“台桌区域 ID”。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '对应JSON字段:tableStatusName,说明::table_status 的中文名称,仅为展示用途。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '对应JSON字段:table_cloth_use_Cycle,说明:(推测):,示例值及对应分析:台呢使用周期阈值,例如达到某个秒数后提醒更换;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '对应JSON字段:table_cloth_use_time,说明:(结合命名和数值特征):,示例值及对应分析:台呢使用累计时长,单位极大概率为“秒”:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '对应JSON字段:table_name,说明::台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '对应JSON字段:table_price,说明:(结构角度):,示例值及对应分析:设计上应为“台的基础单价”字段(例如按小时或按局单价);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '对应JSON字段:table_status,说明::台当前运行状态,真实反映某一时刻台的占用/暂停情况。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '对应JSON字段:temporary_light_second,说明:(推测):临时点灯时长(秒),例如手动临时开灯一段时间。,示例值及对应分析:本门店未使用。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '对应JSON字段:virtual_table,说明:(推测):,示例值及对应分析:0:物理台(实体存在的桌);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS '对应JSON字段:table_fee_discount_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '对应JSON字段:id,说明::台费打折 / 调整流水主键 ID。,示例值及对应分析:作用:在“台费调账表”中唯一标识一条折扣/调账操作。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:标识记录属于哪一个商户(同一个“非球科技”租户)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本批数据全部为同一家门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,用于报表时直接读取,无需再联门店档案。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '对应JSON字段:site_table_id,说明::台桌 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '对应JSON字段:tableProfile,说明::折扣发生时,对应台桌的配置信息快照。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的“台桌区域 ID”。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '对应JSON字段:adjust_type,说明:(根据文件含义 + 命名 + 数据):,示例值及对应分析:文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '对应JSON字段:ledger_amount,说明:(关键点):,示例值及对应分析:通过与 台费流水.json 做对比,可以明确:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '对应JSON字段:ledger_count,说明::,示例值及对应分析:这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '对应JSON字段:ledger_name,说明:(推测):,示例值及对应分析:设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '对应JSON字段:ledger_status,说明::,示例值及对应分析:1:生效调整(当前有效的台费打折 / 调账记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '对应JSON字段:applicant_id,说明::打折/调账申请人 ID。,示例值及对应分析:作用:记录谁发起了这次台费调整。 本时段内所有调整均由同一位员工发起。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '对应JSON字段:applicant_name,说明::申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '对应JSON字段:operator_id,说明::实际执行调账操作的操作员 ID。,示例值及对应分析:说明:这段时间内,“申请人”和“操作员”是同一个人。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单/小票 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '对应JSON字段:create_time,说明::台费调整记录的创建时间,即打折操作被执行的时间戳。,示例值及对应分析:说明:与台费流水中的 create_time(结算时间)相互配合,可以还原调整发生于结账之前还是之后。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS '对应JSON字段:table_fee_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '对应JSON字段:id,说明::台费流水记录主键(事实表主键)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。本文件所有记录都属于同一租户。,示例值及对应分析:关联:与所有其它 JSON 中的 tenant_id 一致,用于跨表做“商户维度”的过滤。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID,本次数据全部来自同一门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::当前门店的完整档案快照,冗余到流水表中,便于报表直接读取而无需再联表门店档案。,示例值及对应分析:三、与其它 JSON 的结构关联关系(从字段层面)';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店内“台桌区域” ID(站在门店物理布局的角度)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '对应JSON字段:site_table_area_name,说明::台桌区域的名称,用于门店表现和区域统计。,示例值及对应分析:4. 会员维度与相关字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的台桌区域 ID(品牌层面的同一类区域)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,是整笔订单的主编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '对应JSON字段:order_pay_id,说明::订单支付记录 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单号/结账 ID,对应一次结账操作。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '对应JSON字段:ledger_name,说明::台号名称,实际展示给员工/顾客看的桌台编号。,示例值及对应分析:备注:与 site_table_id 一一对应,是桌台维表中的名称字段冗余到流水里的快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '对应JSON字段:ledger_amount,说明::按单价与计费时长计算出的原始应收台费金额。,示例值及对应分析:近似关系:ledger_amount ≈ ledger_unit_price × ledger_count / 3600,考虑到四舍五入会有小数差。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计费秒数,计费用秒数(应收时长)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::台费结算时设置的 每小时单价/计费单价。,示例值及对应分析:用途:与 ledger_count 共同决定原始应收额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):,示例值及对应分析:1:正常已结算台费;';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账上的计费起始时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账上的计费结束时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '对应JSON字段:start_use_time,说明::台开始使用的时间(实际开台时间)。,示例值及对应分析:特点:在数据中,与 ledger_start_time 完全相同(见下)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '对应JSON字段:last_use_time,说明::最后使用/操作时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '对应JSON字段:real_table_use_seconds,说明::实际使用的总秒数(系统真实统计的使用时长)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '对应JSON字段:real_table_charge_money,说明::台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '对应JSON字段:add_clock_seconds,说明::加钟秒数,在原有使用基础上追加的时长。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '对应JSON字段:adjust_amount,说明::调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '对应JSON字段:coupon_promotion_amount,说明::由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。,示例值及对应分析:特点:当 real_table_charge_money = 0 且该字段为 ledger_amount 时,说明整笔台费是由券促销全额承担。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '对应JSON字段:member_discount_amount,说明:上文已说明,这里补充与金额的结构关系:,示例值及对应分析:功能:表示由会员折扣或会员权益承担的那部分金额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '对应JSON字段:used_card_amount,说明::由储值卡、次卡等“卡内余额”抵扣的金额。,示例值及对应分析:说明:字段设计已预留,但本段时间内台费没有通过储值卡扣款,或者卡扣款在其他表体现。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '对应JSON字段:mgmt_fee,说明:(推测):管理费字段,用于未来支持“台费附加管理费/服务费”的功能。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '对应JSON字段:service_money,说明:(推测):门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。,示例值及对应分析:说明:当前门店未启用此字段结算台费。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '对应JSON字段:fee_total,说明::各种附加费用(如管理费、服务费)合计值。,示例值及对应分析:说明:和 mgmt_fee 一样,目前作为预留字段,没有实际使用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):,示例值及对应分析:1:该台费记录对应的是一个独立计费单元(单独结算的桌费);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '对应JSON字段:member_id,说明::门店/租户内的会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID,负责开台/结账的员工账号 ID。,示例值及对应分析:关联:与员工/账号体系中的用户 ID 对应(与助教账号的 user_id 属于同一种 ID 体系)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '对应JSON字段:salesman_name,说明::业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。,示例值及对应分析:当前门店未启用该字段做提成归属。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属机构/部门 ID。,示例值及对应分析:8. 状态 / 标记类字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员的用户 ID(与 salesman_name 搭配)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '对应JSON字段:create_time,说明::这条台费流水记录的创建时间,通常接近结账时间。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS '对应JSON字段:goods_stock_movements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '对应JSON字段:siteGoodsStockId,说明::门店某个“商品库存记录”的主键 ID。,示例值及对应分析:特点:每条库存变动记录对应一个 siteGoodsStockId,同一个商品可能在不同库存记录中出现(例如不同仓位或不同批次)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '对应JSON字段:tenantId,说明::租户/品牌 ID。,示例值及对应分析:观测:全部记录相同值,说明属于同一商户。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:观测:本文件中所有记录的 siteId 都相同,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '对应JSON字段:siteGoodsId,说明::门店维度的商品 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '对应JSON字段:goodsName,说明::商品名称。,示例值及对应分析:示例值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明::商品一级分类 ID。,示例值及对应分析:观测:当前 100 条样本中约有 5 个不同 ID,对应如“酒水类”“食品小吃类”“香烟类”等大类(仅从命名与商品名推断)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '对应JSON字段:goodsSecondCategoryId,说明::商品二级分类 ID。,示例值及对应分析:观测:样本中约有 7 个不同 ID,如饮料中的“矿泉水/功能饮料/碳酸饮料”等。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '对应JSON字段:unit,说明::库存计量单位。,示例值及对应分析:说明:库存数量(startNum、endNum、changeNum)均以这里的单位计数。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '对应JSON字段:price,说明::商品单价(单位金额)。,示例值及对应分析:观测特征:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '对应JSON字段:stockType,说明:(基于数据行为推断):,示例值及对应分析:1:出库类变动 典型情况是销售出库,库存减少 1 或 2;例如顾客点了一瓶饮料,对应一条 stockType=1, changeNum=-1 的记录。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '对应JSON字段:changeNum,说明::本次库存数量变化值。,示例值及对应分析:特点及取值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '对应JSON字段:startNum,说明::变动前(这次出入库之前)的库存数量。,示例值及对应分析:示例: 如记录:startNum = 28, changeNum = -1, endNum = 27。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '对应JSON字段:endNum,说明::变动后(出入库之后)的库存数量。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '对应JSON字段:changeNumA,说明::辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。,示例值及对应分析:结论: startNumA / endNumA / changeNumA 是为“一个商品有两种计量单位(如箱与瓶)”而设计的预留字段。 目前门店只在单一单位层面管理库存,故全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '对应JSON字段:startNumA,说明:(推测):辅助计量单位的起始库存(例如件/箱等第二单位)。,示例值及对应分析:当前门店在样本时间段内没有启用多单位库存管理,因此全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '对应JSON字段:endNumA,说明::辅助单位的变动后库存,同样未启用。,示例值及对应分析:?? goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '对应JSON字段:remark,说明::备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。,示例值及对应分析:当前样本中没有填入任何备注,但字段已预留,适用于盘点或手工调整场景。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '对应JSON字段:operatorName,说明::执行此次库存变动的操作人。,示例值及对应分析:观测值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '对应JSON字段:createTime,说明::这条库存变动记录的创建时间,即发生库存变更的时间点。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS '对应JSON字段:stock_goods_category_tree.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '对应JSON字段:id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '对应JSON字段:tenant_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '对应JSON字段:category_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '对应JSON字段:alias_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '对应JSON字段:pid,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '对应JSON字段:business_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '对应JSON字段:open_salesman,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '对应JSON字段:categoryBoxes,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '对应JSON字段:sort,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '对应JSON字段:is_warehousing,说明::分类节点主键 ID(在商品分类维度中的唯一标识)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS '对应JSON字段:goods_stock_summary.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '对应JSON字段:siteGoodsId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '对应JSON字段:goodsName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '对应JSON字段:goodsUnit,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '对应JSON字段:goodsCategorySecondId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '对应JSON字段:categoryName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '对应JSON字段:rangeStartStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '对应JSON字段:rangeEndStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '对应JSON字段:rangeIn,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '对应JSON字段:rangeOut,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '对应JSON字段:rangeSale,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '对应JSON字段:rangeSaleMoney,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '对应JSON字段:rangeInventory,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '对应JSON字段:currentStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS '对应JSON字段:payment_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '对应JSON字段:id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '对应JSON字段:site_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '对应JSON字段:siteProfile,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '对应JSON字段:relate_type,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '对应JSON字段:relate_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '对应JSON字段:pay_amount,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '对应JSON字段:pay_status,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '对应JSON字段:pay_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '对应JSON字段:create_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '对应JSON字段:payment_method,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS '对应JSON字段:refund_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '对应JSON字段:id,说明::本条 退款流水 的唯一 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,全系统维度标识该商户。,示例值及对应分析:特点:本文件中所有记录相同。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '对应JSON字段:tenantName,说明::租户(商户)名称。,示例值及对应分析:特点:本文件中固定为“朗朗桌球”,完全冗余于 siteProfile.shop_name。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:本文件中所有记录相同(单门店)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。包含字段包括但不限于:,示例值及对应分析:id:门店 ID(= site_id);';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '对应JSON字段:relate_type,说明::本退款对应的“业务类型”。,示例值及对应分析:结合支付记录的 relate_type 推测:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '对应JSON字段:relate_id,说明::本次退款关联的业务 ID。,示例值及对应分析:对于 relate_type = 2:应该对应某个订单/结算的主键;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '对应JSON字段:pay_sn,说明:?????? refund_transactions-Analysis.md,示例值及对应分析:?? refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '对应JSON字段:pay_amount,说明::本次退款的 资金变动金额。,示例值及对应分析:特征很重要:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):,示例值及对应分析:设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '对应JSON字段:round_amount,说明:(推测):,示例值及对应分析:舍入金额/抹零金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '对应JSON字段:pay_status,说明:(推测):,示例值及对应分析:支付/退款状态枚举:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '对应JSON字段:pay_time,说明::退款在支付渠道层面实际发生的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '对应JSON字段:create_time,说明::本条退款流水在系统内创建时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '对应JSON字段:payment_method,说明:(推测):,示例值及对应分析:支付/退款的 方式类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '对应JSON字段:pay_terminal,说明:(推测):,示例值及对应分析:退款所使用的 终端类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '对应JSON字段:pay_config_id,说明:(推测):,示例值及对应分析:支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:(推测):,示例值及对应分析:线上支付的 渠道编号,例如:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '对应JSON字段:online_pay_type,说明:(推测):,示例值及对应分析:在线退款的类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '对应JSON字段:channel_fee,说明:(推测):,示例值及对应分析:第三方支付渠道对本次退款收取的手续费;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '对应JSON字段:channel_payer_id,说明:(推测):,示例值及对应分析:支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '对应JSON字段:channel_pay_no,说明:(推测):,示例值及对应分析:第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '对应JSON字段:member_id,说明::,示例值及对应分析:租户内部的会员 ID(对应会员档案中的某个主键)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '对应JSON字段:member_card_id,说明::,示例值及对应分析:关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '对应JSON字段:cashier_point_id,说明:(推测):,示例值及对应分析:收银点 ID,例如前台 1、前台 2、自助机等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '对应JSON字段:operator_id,说明::,示例值及对应分析:执行该退款操作的操作员 ID。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '对应JSON字段:action_type,说明:(推测):,示例值及对应分析:行为类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '对应JSON字段:check_status,说明:(推测):,示例值及对应分析:审核状态:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '对应JSON字段:is_revoke,说明:(推测):,示例值及对应分析:是否撤销型退款/撤销原支付:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '对应JSON字段:balance_frozen_amount,说明:(推测):,示例值及对应分析:涉及会员储值卡退款时,暂时冻结的余额金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '对应JSON字段:card_frozen_amount,说明::与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。,示例值及对应分析:状态同上:本数据中未发生“卡冻结退款”。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS '对应JSON字段:platform_coupon_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '对应JSON字段:id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '对应JSON字段:verify_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '对应JSON字段:certificate_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '对应JSON字段:coupon_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '对应JSON字段:coupon_channel,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '对应JSON字段:groupon_type,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '对应JSON字段:group_package_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '对应JSON字段:sale_price,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '对应JSON字段:coupon_free_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '对应JSON字段:coupon_cover,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '对应JSON字段:coupon_remark,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '对应JSON字段:use_status,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '对应JSON字段:consume_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '对应JSON字段:create_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '对应JSON字段:deal_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '对应JSON字段:channel_deal_id,说明:任意一个 ID 字段缺失时(如部分记录 deal_id=0),仍然可以通过其他字段(coupon_name + sale_price + coupon_money + channel_deal_id)唯一识别该产品。,示例值及对应分析:这种多字段冗余,结构上提升了抗“配置缺失”的能力。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '对应JSON字段:site_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '对应JSON字段:site_order_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '对应JSON字段:table_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '对应JSON字段:operator_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '对应JSON字段:operator_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '对应JSON字段:is_delete,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS '对应JSON字段:tenant_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 tenant_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '对应JSON字段:id,说明::商品档案主键 ID,唯一标识一条商品。,示例值及对应分析:作用:作为其他业务表(销售明细、库存流水、门店商品表等)的外键,通常以 tenant_goods_id 或类似字段出现。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:和其它 JSON 中的 tenant_id / tenantId 一致,用于区分不同商户(本次数据只包含同一租户)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称(前台展示名称)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条码(EAN 等),目前未维护。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '对应JSON字段:categoryName,说明::商品一级分类名称(业务可读)。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '对应JSON字段:unit,说明::计量单位。,示例值及对应分析:取值(共 12 种左右):';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '对应JSON字段:goods_number,说明::商品内部编码(自定义货号/系统货号)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '对应JSON字段:goods_state,说明:(推测):商品状态(上架/下架等)。,示例值及对应分析:1:正常/上架;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明:(推测):销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。,示例值及对应分析:现有数据只有一个值,说明本门店目前仅通过一种渠道销售这些商品。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(推测):是否允许参与折扣/打折。,示例值及对应分析:1:允许折扣;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(推测):,示例值及对应分析:字面意思是“是否允许门店间调拨/门店级操作”:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效商品);';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明:(推测):是否启用库存管理。,示例值及对应分析:1:该商品纳入库存管理;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '对应JSON字段:isInSite,说明:(从命名推测):是否在当前门店启用/上架。,示例值及对应分析:现象:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '对应JSON字段:cost_price,说明::成本价格。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(推测):,示例值及对应分析:不同的成本价格来源或计算方式,如:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '对应JSON字段:market_price,说明::商品标价 / 售价(标准销售单价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::该商品允许售卖的最低价格(底价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '对应JSON字段:common_sale_royalty,说明:(推测):普通销售提成比例或提成金额的配置字段。,示例值及对应分析:当前门店未在商品档案上配置员工提成规则,全部为 0。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '对应JSON字段:point_sale_royalty,说明:(推测):积分销售提成/积分赠送规则相关配置。,示例值及对应分析:当前同样未启用。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::拼音首字母/助记码。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '对应JSON字段:commodityCode,说明::,示例值及对应分析:与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '对应JSON字段:commodity_code,说明::商品编码(通常为对外商品编码或条码)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品封面图片 URL 地址。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '对应JSON字段:supplier_id,说明::供应商 ID,用于关联到供应商档案。,示例值及对应分析:当前所有商品都未挂接具体供应商(或门店未使用供应链管理模块)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '对应JSON字段:remark_name,说明:(从命名推断):商品备注名/别名,通常用来配置简写或特殊显示名称。,示例值及对应分析:当前门店尚未使用该字段,字段设计为将来扩展预留。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '对应JSON字段:create_time,说明::商品档案创建时间。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '对应JSON字段:update_time,说明::商品档案最近一次修改时间。,示例值及对应分析:分布:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '对应JSON字段:group_buy_packages.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '对应JSON字段:id,说明::门店侧套餐 ID,本文件内部的主键。,示例值及对应分析:特点:17 条记录中均为不同的大整数 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '对应JSON字段:package_id,说明::“上层套餐 ID” 或“总部/系统级套餐 ID”。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '对应JSON字段:package_name,说明::团购套餐名称,用于前台展示和核销界面。,示例值及对应分析:示例:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '对应JSON字段:selling_price,说明:(结合字段命名):,示例值及对应分析:语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '对应JSON字段:coupon_money,说明::券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。,示例值及对应分析:示例(对应套餐名称):';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '对应JSON字段:date_type,说明:(推测):,示例值及对应分析:典型用法:区分“全部日期可用 / 工作日 / 周末 / 指定日期”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '对应JSON字段:date_info,说明:(推测):,示例值及对应分析:预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '对应JSON字段:start_time,说明::套餐开始生效的日期时间。,示例值及对应分析:示例:"2025-07-20 00:00:00" 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '对应JSON字段:end_time,说明::套餐失效的日期时间(到这个时间点后不可使用)。,示例值及对应分析:示例:形如 "2025-11-30 23:59:59",部分记录使用 9999-12-31 23:59:59 风格的极大日期表示长期有效(本数据中如有这种值,可解读为“长期有效”)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '对应JSON字段:start_clock,说明::每日可用起始时间点(第一段)。,示例值及对应分析:说明:配合 end_clock 使用,定义一个日内时段。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '对应JSON字段:end_clock,说明::每日可用的结束时间点(第一段)。,示例值及对应分析:结构说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '对应JSON字段:add_start_clock,说明:(推测):附加可用时间段的起始时间(第二段)。,示例值及对应分析:例如有的套餐可以在两个不连续的时段使用:早场 + 夜场,则可用第一段 start_clock / end_clock 和第二段 add_start_clock / add_end_clock 组合。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '对应JSON字段:add_end_clock,说明::附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。,示例值及对应分析:整体理解:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '对应JSON字段:duration,说明::套餐内包含的时长(秒)。,示例值及对应分析:与名称一致:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '对应JSON字段:usable_count,说明::可使用次数上限。,示例值及对应分析:数据特征说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '对应JSON字段:usable_range,说明:吻合(A区中八/B区中八/斯诺克/KTV/包厢等)。,示例值及对应分析:通过该关联,系统在核销时可以校验:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '对应JSON字段:table_area_id,说明:(推测):,示例值及对应分析:原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '对应JSON字段:table_area_name,说明::套餐适用的“门店台区名称”,用于显示和筛选。,示例值及对应分析:说明:这个字段是对区域 ID 维度的文字描述,便于直观理解。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '对应JSON字段:table_area_id_list,说明:(推测):,示例值及对应分析:用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明:(推测):,示例值及对应分析:与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '对应JSON字段:tenant_table_area_id_list,说明:(推测):,示例值及对应分析:实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:全表值相同,且与其他 JSON 文件中的 site_id 一致,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '对应JSON字段:site_name,说明::门店名称。,示例值及对应分析:观测值:全部为 "朗朗桌球"。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '对应JSON字段:tenant_id,说明::租户 ID(品牌/商户 ID)。,示例值及对应分析:特点:全表值相同,说明所有套餐定义属于同一商户(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '对应JSON字段:card_type_ids,说明:(推测):,示例值及对应分析:原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '对应JSON字段:group_type,说明:(推测):,示例值及对应分析:团购类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '对应JSON字段:system_group_type,说明:(推测):,示例值及对应分析:系统内对团购类型更底层的划分,比如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '对应JSON字段:type,说明:(推测):,示例值及对应分析:内部业务子类型,具体含义需要结合系统文档;仅从数据无法确定是“台费类 vs 包厢类”还是“平台套餐 vs 自定义套餐”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '对应JSON字段:effective_status,说明:(结合命名和数据特征推断):,示例值及对应分析:1:有效(在当前时间区间内、配置正常,可核销使用)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '对应JSON字段:is_enabled,说明::启用状态。,示例值及对应分析:从其他表的统一风格来看,1 一般表示“启用 / 上架”,2 表示“停用 / 下架”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '对应JSON字段:max_selectable_categories,说明:?????? group_buy_packages-Analysis.md,示例值及对应分析:?? group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '对应JSON字段:area_tag_type,说明:(推测):区域标记类型:,示例值及对应分析:1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '对应JSON字段:creator_name,说明::创建人信息,一般包含“角色:姓名”。,示例值及对应分析:示例:"管理员:郑丽珊"';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '对应JSON字段:create_time,说明::该套餐在系统中创建的时间。,示例值及对应分析:特点:每条记录各不相同,覆盖了 2025-07 至 2025-10 的创建时间。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS '对应JSON字段:group_buy_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '对应JSON字段:id,说明::本条“团购套餐流水”记录的 主键 ID。,示例值及对应分析:作用:唯一标识一条券使用到台费上的记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特点:全表值相同,说明所有记录属于同一租户。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,与其它 JSON 中一致。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '对应JSON字段:siteName,说明::门店名称,冗余展示用。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '对应JSON字段:table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '对应JSON字段:tableName,说明::本次使用券所关联的 球台名称/台号。,示例值及对应分析:关联:对应台桌列表中的 table_name / table_no,通过 table_id 进一步关联。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '对应JSON字段:tableAreaName,说明::该球台所属的 台区名称。,示例值及对应分析:关联:与台区配置中的 area_name 含义一致,与团购套餐定义中的 table_area_name 一致。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单 ID(小票结账主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:(推测):,示例值及对应分析:指向支付记录表中的支付流水 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单中“券使用记录”的 ID。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '对应JSON字段:order_coupon_channel,说明:(推测):,示例值及对应分析:券渠道类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明::团购券券码,核销时扫描/录入的字符串。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明::本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '对应JSON字段:coupon_origin_id,说明:(推测):,示例值及对应分析:平台/上游系统中的券记录主键 ID,“券来源 ID”。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '对应JSON字段:ledger_name,说明::台费侧关联的“团购项目名称”(记账名)。,示例值及对应分析:结构上通常来源于团购套餐定义的 package_name,或由系统在创建活动时生成。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。,示例值及对应分析:当前门店未对团购项目做进一步分组。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::本次券实际冲抵台费的金额。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '对应JSON字段:ledger_count,说明::按此次优惠实际计算的“核销秒数”。,示例值及对应分析:结构观察:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。,示例值及对应分析:作用:配合 ledger_count 用于计算这一条券在台费层面对应的金额(理论上应接近 = 单价 × 秒数/3600)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):流水状态。,示例值及对应分析:1:正常有效;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '对应JSON字段:table_charge_seconds,说明::本次结算中该球台总计计费的秒数(整台的台费计费时间)。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '对应JSON字段:promotion_activity_id,说明:(推测):团购/促销活动 ID。,示例值及对应分析:对应平台或内部促销活动的主键,每个活动通常绑定一个或多个具体套餐(promotion_coupon_id)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '对应JSON字段:promotion_coupon_id,说明::团购套餐定义 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '对应JSON字段:promotion_seconds,说明::团购套餐定义的“标准时长”(券本身标称的可用时长)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '对应JSON字段:offer_type,说明:(推测):优惠类型。,示例值及对应分析:在券适用多个优惠方式的系统中,一般用来区分“满减/折扣/代金券/套餐券”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '对应JSON字段:assistant_promotion_money,说明::分摊到“助教服务”的促销金额。,示例值及对应分析:当前场景下,团购券只与台费相关,未涉及助教的金额抵扣。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '对应JSON字段:assistant_service_promotion_money,说明::进一步细分助教服务的促销金额。,示例值及对应分析:当前未使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '对应JSON字段:table_service_promotion_money,说明::本次券使用中,分摊到“台费服务费”部分的促销金额。,示例值及对应分析:当前样本中,促销金额都在 ledger_amount 中体现,该字段未单独拆出。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '对应JSON字段:goods_promotion_money,说明::本次券使用中,分摊到“商品”部分的促销金额。,示例值及对应分析:当前数据中,所有团购券都只用于抵扣台费,没有用来抵扣商品,因此该字段为 0。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '对应JSON字段:recharge_promotion_money,说明::来自“充值类优惠”的分摊金额(例如储值赠送部分)。,示例值及对应分析:当前所有数据为 0,但结构上已经预留了“多来源促销金额分摊”的能力。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '对应JSON字段:reward_promotion_money,说明::本次促销中,属于“奖励金/积分抵扣”的金额。,示例值及对应分析:当前没有使用此维度的促销。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '对应JSON字段:goodsOptionPrice,说明:(按命名推测):商品规格价格,用于商品类促销分摊时使用。,示例值及对应分析:当前在“团购套餐流水”中未被实际使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织 ID。,示例值及对应分析:以上 4 个销售相关字段在当前门店的团购套餐使用中都未启用,仅作为结构预留。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员角色 ID。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员/业务员用户 ID。,示例值及对应分析:当前所有团购套餐流水都未指定独立的营业员。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '对应JSON字段:operator_id,说明::执行本次核销/结算操作的 操作员 ID。,示例值及对应分析:关联:可以与员工档案表中的 id 对应(当前导出中员工表未单独给出,但风格和其它表一致)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '对应JSON字段:operator_name,说明::操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独作为一条订单行。,示例值及对应分析:1:以独立条目方式进行结算(绝大部分记录如此)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '对应JSON字段:create_time,说明::本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。,示例值及对应分析:用法:可用于按时间范围过滤团购使用记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS '对应JSON字段:settlement_ticket_details.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '对应JSON字段:orderSettleId,说明::同 data.data.orderSettleId,为结算单 ID 的冗余。,示例值及对应分析:orderType';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '对应JSON字段:actualPayment,说明::本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。,示例值及对应分析:一般应与支付记录中各支付流水金额汇总相匹配。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '对应JSON字段:adjustAmount,说明::台费层面的人工调价金额(仅台费部分)。,示例值及对应分析:memberDiscountAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '对应JSON字段:assistantManualDiscount,说明::针对“助教项目”的人工减免金额汇总(整单维度)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '对应JSON字段:balanceAmount,说明::本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。,示例值及对应分析:对应 结账记录.json 的同名字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '对应JSON字段:cashierName,说明::本单结算操作员名称(带角色前缀文字)。,示例值及对应分析:对应员工维表中的某个账号,便于小票上展示“收银员:XXX”。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '对应JSON字段:consumeMoney,说明::本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。,示例值及对应分析:对应 结账记录.json 的 consumeMoney 字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '对应JSON字段:couponAmount,说明::本单由优惠券抵扣的金额汇总。,示例值及对应分析:结构上:应与 orderCouponLedgers.discountAmount 的合计存在关系,但当前导出未填充。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '对应JSON字段:deliveryAddress,说明::配送地址(若存在外送业务时使用)。,示例值及对应分析:对于球房场景,当前时间范围内未使用。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '对应JSON字段:deliveryFee,说明::配送费金额(如果支持外送业务)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '对应JSON字段:ledgerAmount,说明::按台账口径对应的金额,一般与 discountAmount 一致或有固定关系。,示例值及对应分析:rewardPromotionMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '对应JSON字段:memberDeductAmount,说明:(结构上):会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '对应JSON字段:memberOfferAmount,说明::由“会员权益/折扣”产生的优惠金额总计(整单维度)。,示例值及对应分析:与 memberProfile 以及台费/商品明细中的 memberDiscountAmount 有对应关系。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '对应JSON字段:onlineReturnAmount,说明::本单通过线上支付渠道退回的金额(如微信/支付宝退款)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '对应JSON字段:orderRemark,说明::订单备注,由收银员录入,用于记录与本单相关的特殊说明。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '对应JSON字段:orderSettleNumber,说明:(推测):结算单编号(与 ID 独立的一套编号体系,如流水号)。当前导出时间段内未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '对应JSON字段:payMemberBalance,说明:(结构上):使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '对应JSON字段:payTime,说明::本单最终支付成功时间。,示例值及对应分析:和 结账记录.json 中的 payTime 对应,一般与 支付记录.create_time/pay_time 在同一时间段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '对应JSON字段:paymentMethod,说明::结算主支付方式编码(汇总视角)。,示例值及对应分析:对应 结账记录.json 中的 paymentMethod 字段;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '对应JSON字段:pointDiscountCost,说明::积分抵扣对应的成本金额(成本侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '对应JSON字段:pointDiscountPrice,说明::积分抵扣对应的金额(售价侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '对应JSON字段:prepayMoney,说明::预付金/定金在本单中使用的金额。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '对应JSON字段:refundAmount,说明::本单涉及的退款金额(汇总)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '对应JSON字段:returnGoodsAmount,说明::本单涉及的退货金额汇总。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '对应JSON字段:rewardName,说明:(结构上):用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '对应JSON字段:settleType,说明::结算类型字符串标识。,示例值及对应分析:"SiteOrder":店内消费订单结算。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '对应JSON字段:siteAddress,说明::门店地址(详细地址)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '对应JSON字段:siteBusinessTel,说明::门店电话。,示例值及对应分析:用途:用于小票打印上的客服电话。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '对应JSON字段:siteName,说明::门店名称,如“朗朗桌球”。,示例值及对应分析:用途:小票上展示门店名。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '对应JSON字段:tenantId,说明::租户 / 商户 ID(品牌维度)。,示例值及对应分析:当前数据:恒定为同一值,表示所有记录都来自同一商户。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '对应JSON字段:tenantName,说明::租户名称,如“朗朗桌球”。,示例值及对应分析:当前数据:全表统一一个值。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '对应JSON字段:ticketCustomContent,说明::自定义小票内容,如商家自定义宣传语、条款等。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '对应JSON字段:ticketRemark,说明::小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '对应JSON字段:voucherMoney,说明::代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '对应JSON字段:memberProfile,说明::,示例值及对应分析:不是会员卡主键,而是本次结账时的会员信息快照;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '对应JSON字段:orderItem,说明::本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。,示例值及对应分析:下面专门展开 orderItem 及其子结构。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '对应JSON字段:tenantMemberCardLogs,说明:?????? settlement_ticket_details-Analysis.md,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS '对应JSON字段:store_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '对应JSON字段:id,说明::门店商品 ID,门店维度的商品主键。,示例值及对应分析:用途:在其它文件中经常以 site_goods_id 的名字出现,与这里的 id 一致,用来关联库存记录、销售记录等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。同一品牌下多个门店共享一个 tenant_id。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一家门店“朗朗桌球”),和其它 JSON 中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '对应JSON字段:siteName,说明::门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。,示例值及对应分析:2. 商品标识和分类维度';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户/品牌维度的商品 ID,相当于“全局商品 ID”。,示例值及对应分析:用途:用于跨门店或与“商品档案(商品档案.json)”对齐时使用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。,示例值及对应分析:用途:业务展示字段,历史流水里也会冗余存一份商品名。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条形码(如 EAN-13 编码),用于扫码销售。此字段设计为可填,但此店目前未配置。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '对应JSON字段:oneCategoryName,说明::一级分类名称,如“零食”“酒水”“服务费”等。,示例值及对应分析:说明:与 goods_category_id 一一对应,是易读文本字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '对应JSON字段:twoCategoryName,说明::二级分类名称,如“面”“洋酒”“纸巾”等。,示例值及对应分析:说明:与 goods_second_category_id 对应。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '对应JSON字段:unit,说明::商品计量单位(销售单位)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '对应JSON字段:sale_price,说明::商品标准销售价(挂牌价),单位为元。,示例值及对应分析:说明:实际结算时可能会打折或用券抵扣,但这个字段表示“定价”。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '对应JSON字段:cost_price,说明::商品成本价(单件成本)。,示例值及对应分析:观察:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(结合成本字段推测):,示例值及对应分析:1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::最低允许成交价(限价)。,示例值及对应分析:用法逻辑(推测):';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '对应JSON字段:safe_stock,说明::安全库存量(阈值),低于该值时系统可以提示补货。,示例值及对应分析:当前门店尚未设置安全库存,所以全部为 0,仅起到结构占位作用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '对应JSON字段:stock,说明::当前可用库存数量(以 unit 为单位)。,示例值及对应分析:特征:可以是 0(库存卖完),也可以非常大(例如纸巾、茶位费这种按“份”计的虚拟库存设定)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '对应JSON字段:stock_A,说明:(系统设计):副单位库存数量。如果商品存在双单位(例如箱/瓶),stock_A 通常用于记录副单位库存。当前门店没有启用副单位库存管理,因此为 0。,示例值及对应分析:batch_stock_quantity';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '对应JSON字段:sale_num,说明::在当前统计口径下的销售数量(总销量,单位同 unit)。,示例值及对应分析:特征:和 total_sales 完全一致(当前导出时的统计口径下),说明两者是同一统计周期。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '对应JSON字段:total_purchase_cost,说明::总采购成本,单位为元。,示例值及对应分析:当前数据:与 provisional_total_cost 完全相等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '对应JSON字段:total_sales,说明:(从命名看):累计销售数量。,示例值及对应分析:实际:当前数据中 total_sales == sale_num,说明此接口的统计区间 = “截至当前的全部历史”,因此数量一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '对应JSON字段:average_monthly_sales,说明::平均月销量(件/月),根据某个统计周期内的销售数据折算而来。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '对应JSON字段:enable_status,说明:(结合名称与常见编码):,示例值及对应分析:1:启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '对应JSON字段:audit_status,说明:(典型业务语义):,示例值及对应分析:2:审核通过。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '对应JSON字段:goods_state,说明:类型:int,枚举,示例值及对应分析:观察值:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效档案);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明::是否纳入库存管理。,示例值及对应分析:1:启用库存管理(会有出入库流水)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(结合命名):,示例值及对应分析:是否允许参与折扣。当前全部为 1,说明所有商品都允许打折。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(结合命名与值分布):,示例值及对应分析:表示是否允许跨门店调拨或跨站点共享库存。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '对应JSON字段:forbid_sell_status,说明:类型:int,枚举,示例值及对应分析:观察值:全部为 1。';
+COMMENT ON COLUMN billiards_ods.store_goods_master."freeze" IS '对应JSON字段:freeze,说明::冻结状态。,示例值及对应分析:0:未冻结;';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '对应JSON字段:send_state,说明:(命名趋近“上架状态/可售状态”):,示例值及对应分析:1:可销售/可下单。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '对应JSON字段:custom_label_type,说明:(推测):自定义标签类型。,示例值及对应分析:1:使用系统默认标签(未出现);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '对应JSON字段:option_required,说明:(推测):是否需要在销售时选择规格/选项。,示例值及对应分析:1:不要求额外选项(单规格商品);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明::销售渠道类型。,示例值及对应分析:常见模式:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '对应JSON字段:remark,说明::商品备注(可以写口味说明、供应商、注意事项等)。当前尚未使用。,示例值及对应分析:sort';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::商品名称的拼音首字母缩写,有时多个别名用逗号分隔。,示例值及对应分析:作用:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '对应JSON字段:create_time,说明::门店商品档案创建时间(商品在门店建立档案的时间点)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '对应JSON字段:update_time,说明::最后一次修改该商品档案的时间(包括价格调整、状态变更等)。,示例值及对应分析:days_available';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS '对应JSON字段:store_goods_sales_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '对应JSON字段:id,说明::本条「门店销售流水」记录的主键 ID。,示例值及对应分析:用途:在系统内部唯一标识这一条销售明细。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特征:所有记录为同一个值,对应「非球科技系统中你的商户」。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '对应JSON字段:site_id,说明::门店 ID(系统主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '对应JSON字段:site_goods_id,说明::门店商品 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户(品牌)级商品 ID(全局商品 ID)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '对应JSON字段:order_settle_id,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '对应JSON字段:order_trade_no,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '对应JSON字段:order_goods_id,说明::订单商品明细 ID(订单内部的商品行主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:连接到「支付记录」中的一条支付流水,再通过支付的 relate_type/relate_id 把支付和订单、充值等业务区分开。,示例值及对应分析:对于退款,则通过退款记录里的 relate_type/relate_id 反向关联到原来的订单或支付。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单级优惠券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '对应JSON字段:ledger_name,说明::销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。,示例值及对应分析:说明:业务展示用字段,历史流水即使商品改名,这里会保留当时的名字。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明::销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::原始应收金额,公式上接近 ledger_unit_price × ledger_count。,示例值及对应分析:说明:这是未考虑优惠前的金额基础,用于后续计算折扣和抵扣。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '对应JSON字段:ledger_count,说明::销售数量(以 unit 为单位,unit 字段在门店商品档案中)。,示例值及对应分析:观测值:如 1, 2, 3, 6, 36 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::商品在该次销售中的「结算单价」(元/单位)。,示例值及对应分析:观测值示例:5.0, 8.0, 2.0, 10.0, 72.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '对应JSON字段:ledger_status,说明::销售流水状态。,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '对应JSON字段:discount_money,说明::本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。,示例值及对应分析:典型关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::被优惠券 / 团购券直接抵扣到这条商品明细上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员身份(会员折扣)针对这一行商品产生的优惠金额。,示例值及对应分析:说明:尽管字段存在,但当前实际折扣可能合并反映在 discount_money 中,这个字段没有拆开体现。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '对应JSON字段:option_coupon_deduct_money,说明::由优惠券抵扣“选项价格”的金额。,示例值及对应分析:上面这三个 option_* 字段,是为“主商品 + 选项”的更复杂计价方式预留的,本店当前所有记录都是单规格,选项体系未启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '对应JSON字段:option_member_discount_money,说明::由会员折扣作用在“选项价格”上的优惠金额。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '对应JSON字段:point_discount_money,说明::由积分抵扣的金额(顾客兑换积分抵现金额)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '对应JSON字段:point_discount_money_cost,说明::积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '对应JSON字段:real_goods_money,说明::商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。,示例值及对应分析:观测值:5.0, 10.0, 8.0, 6.0, 4.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '对应JSON字段:cost_money,说明::本条销售对应的成本金额(以元计)。,示例值及对应分析:观测示例:0.01, 0.00, 3.58, 1.79, 0.64 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '对应JSON字段:push_money,说明::本条销售对应的提成金额(给营业员/促销员的提成)。,示例值及对应分析:在启用营业员体系时,这里才会出现正数。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '对应JSON字段:sales_type,说明::销售类型。,示例值及对应分析:1:正常销售;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '对应JSON字段:is_single_order,说明::是否单独订单标识。,示例值及对应分析:1:作为独立明细参与某个订单结算;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '对应JSON字段:goods_remark,说明::商品备注/口味说明/特殊说明。,示例值及对应分析:用途:点单时如果需要额外说明,可以写在这里。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '对应JSON字段:option_price,说明::商品选项(规格/加料)的附加价格。,示例值及对应分析:说明:如加冰、加料、升级大杯等产生附加费用时,理论上应该体现到这里。当前门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '对应JSON字段:option_value_name,说明::商品选项名称(如规格、口味:大杯/小杯,不加冰等)。,示例值及对应分析:结构用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '对应JSON字段:option_name,说明:?????? store_goods_sales_records-Analysis.md,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '对应JSON字段:member_coupon_id,说明::会员券 ID(比如会员专享优惠券)。,示例值及对应分析:当前数据未使用,属于为会员权益预留的字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '对应JSON字段:package_coupon_id,说明::套餐券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:当前门店全部为 0,说明未启用这套销售员分组织的体系。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员的系统角色 ID(例如某个角色代码表示“销售员”)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID(系统账号 ID)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入这笔销售的员工)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,文字冗余。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '对应JSON字段:openSalesman,说明:(结合系统其它文件推断):,示例值及对应分析:1:启用“营业员/销售员”机制(要指定 salesman);';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:非 0:销售记录关联到具体某张桌台(例如顾客在台上点饮料)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明::租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。,示例值及对应分析:2.2 门店 / 球台维度字段';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '对应JSON字段:tenant_goods_category_id,说明::租户级商品一级分类 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '对应JSON字段:create_time,说明::销售记录创建时间,通常就是结账时间或录入时间。,示例值及对应分析:用途:用于按时间维度查询销售流水,与订单层的时间字段对齐。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
diff --git a/tmp/schema_ODS_doc.sql b/tmp/schema_ODS_doc.sql
new file mode 100644
index 0000000..514f931
--- /dev/null
+++ b/tmp/schema_ODS_doc.sql
@@ -0,0 +1,1907 @@
+-- 文件:schema_ODS_doc.sql
+-- 说明:ODS 层 DDL,表名与示例 JSON 前缀对应,用于本地回放/调试。
+-- 编码:UTF-8
+SET client_encoding TO "UTF8";
+
+DROP SCHEMA IF EXISTS billiards_ods CASCADE;
+CREATE SCHEMA IF NOT EXISTS billiards_ods;
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_profiles (
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ system_member_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ mobile TEXT,
+ nickname TEXT,
+ point NUMERIC(18,2),
+ growth_value NUMERIC(18,2),
+ referrer_member_id BIGINT,
+ status INT,
+ user_status INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_profiles IS '对应JSON字段:member_profiles.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_profiles-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_profiles.tenant_id IS '对应JSON字段:tenant_id,说明::,示例值及对应分析:租户/品牌 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.register_site_id IS '对应JSON字段:register_site_id,说明::,示例值及对应分析:会员的注册门店 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.site_name IS '对应JSON字段:site_name,说明::,示例值及对应分析:注册门店名称,属于冗余字段,用于直接展示。';
+COMMENT ON COLUMN billiards_ods.member_profiles.id IS '对应JSON字段:id,说明::,示例值及对应分析:这是“租户内会员账户”的主键 ID。';
+COMMENT ON COLUMN billiards_ods.member_profiles.system_member_id IS '对应JSON字段:system_member_id,说明:(结合其它文件):,示例值及对应分析:这是“系统级会员 ID”,在全平台唯一,用来把一个会员在不同门店/不同卡类型下的账户统一到一个“人”的维度上。';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明:类型:int,示例值及对应分析:唯一值个数:4';
+COMMENT ON COLUMN billiards_ods.member_profiles.member_card_grade_name IS '对应JSON字段:member_card_grade_name,说明::,示例值及对应分析:这是“会员卡种类/等级”的定义字段。';
+COMMENT ON COLUMN billiards_ods.member_profiles.mobile IS '对应JSON字段:mobile,说明::,示例值及对应分析:会员绑定的手机号码。';
+COMMENT ON COLUMN billiards_ods.member_profiles.nickname IS '对应JSON字段:nickname,说明::,示例值及对应分析:会员在当前租户下的显示名称(可以是姓名,也可以是昵称)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.point IS '对应JSON字段:point,说明::,示例值及对应分析:当前积分余额(这条会员账户的积分值)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.growth_value IS '对应JSON字段:growth_value,说明:(按常见会员体系设计):,示例值及对应分析:成长值 / 经验值,用于会员等级晋升的累计指标。';
+COMMENT ON COLUMN billiards_ods.member_profiles.referrer_member_id IS '对应JSON字段:referrer_member_id,说明:(按命名推断):,示例值及对应分析:推荐人会员 ID,用于记录该会员是由哪位老会员推荐。';
+COMMENT ON COLUMN billiards_ods.member_profiles.status IS '对应JSON字段:status,说明:(按命名推断):,示例值及对应分析:帐户状态(偏“卡状态/档案状态”)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.user_status IS '对应JSON字段:user_status,说明:(结合行业惯例):,示例值及对应分析:用户账号状态(偏“用户逻辑”层面的状态)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.create_time IS '对应JSON字段:create_time,说明::,示例值及对应分析:会员账户的创建时间(即这条档案/这张卡在系统中被创建的时间)。';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_profiles.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_balance_changes (
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ registerSiteName TEXT,
+ paySiteName TEXT,
+ id BIGINT PRIMARY KEY,
+ tenant_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ system_member_id BIGINT,
+ memberName TEXT,
+ memberMobile TEXT,
+ card_type_id BIGINT,
+ memberCardTypeName TEXT,
+ account_data NUMERIC(18,2),
+ before NUMERIC(18,2),
+ after NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ from_type INT,
+ payment_method INT,
+ relate_id BIGINT,
+ remark TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_balance_changes IS '对应JSON字段:member_balance_changes.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_id IS '对应JSON字段:tenant_id,说明::租户/商户 ID,本数据中是固定值(同一品牌/商户)。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.site_id IS '对应JSON字段:site_id,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.register_site_id IS '对应JSON字段:register_site_id,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.registerSiteName IS '对应JSON字段:registerSiteName,说明:已在前文说明:办卡门店的 ID 与名称,所有记录一致,说明所有卡均在“朗朗桌球”注册。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.paySiteName IS '对应JSON字段:paySiteName,说明:表示本次余额变动的发生门店,绝大多数也在“朗朗桌球”,少数特殊业务(活动抵用券结算)显示为 site_id=0、paySiteName 为空。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.id IS '对应JSON字段:id,说明::余额变更记录的主键 ID,唯一标识这一条“账户余额变化事件”。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::商户维度的会员 ID(租户内会员主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.tenant_member_card_id IS '对应JSON字段:tenant_member_card_id,说明::会员卡账户 ID,在租户内唯一标识某张卡。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.system_member_id IS '对应JSON字段:system_member_id,说明::系统级(全局)会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberName IS '对应JSON字段:memberName,说明::会员姓名或称呼(非昵称字段)。,示例值及对应分析:说明:例如“陈腾鑫”“胡先生”“江先生”等,多为中文姓名或带“先生”称呼。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberMobile IS '对应JSON字段:memberMobile,说明::会员手机号。,示例值及对应分析:说明:字符型存储,完整手机号,用来识别会员与联系客户。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.card_type_id IS '对应JSON字段:card_type_id,说明::卡种类型 ID,用于区分不同卡种。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.memberCardTypeName IS '对应JSON字段:memberCardTypeName,说明::卡种名称,与 card_type_id 一一对应,是一个 卡种枚举名称。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.account_data IS '对应JSON字段:account_data,说明::本次变动的金额(元),正数表示增加,负数表示减少。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.before IS '对应JSON字段:before,说明::本次变动前,该卡账户的余额(元)。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.after IS '对应JSON字段:after,说明::本次变动后,该卡账户的余额(元)。,示例值及对应分析:重要关系:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):与退款业务相关的金额字段,但在当前这份导出中实际未使用:,示例值及对应分析:可能用于标记“其中有多少金额是以‘退款’形式回流的”,或区分“退回余额”和“原路退回”两种模式。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.from_type IS '对应JSON字段:from_type,说明:(根据金额符号与 remark 综合推断):,示例值及对应分析:1:日常消费扣款';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payment_method IS '对应JSON字段:payment_method,说明:类型:int,枚举,示例值及对应分析:值分布:';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.relate_id IS '对应JSON字段:relate_id,说明:(推测):关联业务记录的 ID:,示例值及对应分析:例如某次充值记录的 ID、某张订单/结算单 ID、某次活动抵用券核销记录 ID 等。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.remark IS '对应JSON字段:remark,说明::,示例值及对应分析:当为空时,说明这条变动没有额外备注说明。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_id IS '对应JSON字段:operator_id,说明::执行此次余额变更操作的员工 ID。,示例值及对应分析:?? member_balance_changes-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(带职位前缀),是对 operator_id 的可读冗余字段。,示例值及对应分析:9. 状态字段与标志';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标记:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.create_time IS '对应JSON字段:create_time,说明::本条余额变更记录的创建时间,通常接近交易发生时间。,示例值及对应分析:说明:可与订单、支付记录的时间做对齐,构造时序链路(但你现在不要求做时序分析,这里只说明结构)。';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_balance_changes.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.member_stored_value_cards (
+ tenant_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ register_site_id BIGINT,
+ site_name TEXT,
+ id BIGINT PRIMARY KEY,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ card_type_id BIGINT,
+ card_no TEXT,
+ card_physics_type TEXT,
+ balance NUMERIC(18,2),
+ denomination NUMERIC(18,2),
+ table_discount NUMERIC(10,4),
+ goods_discount NUMERIC(10,4),
+ assistant_discount NUMERIC(10,4),
+ assistant_reward_discount NUMERIC(10,4),
+ table_service_discount NUMERIC(10,4),
+ assistant_service_discount NUMERIC(10,4),
+ coupon_discount NUMERIC(10,4),
+ goods_service_discount NUMERIC(10,4),
+ assistant_discount_sub_switch INT,
+ table_discount_sub_switch INT,
+ goods_discount_sub_switch INT,
+ assistant_reward_discount_sub_switch INT,
+ table_service_deduct_radio NUMERIC(10,4),
+ assistant_service_deduct_radio NUMERIC(10,4),
+ goods_service_deduct_radio NUMERIC(10,4),
+ assistant_deduct_radio NUMERIC(10,4),
+ table_deduct_radio NUMERIC(10,4),
+ goods_deduct_radio NUMERIC(10,4),
+ coupon_deduct_radio NUMERIC(10,4),
+ assistant_reward_deduct_radio NUMERIC(10,4),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ cardSettleDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ use_scene INT,
+ able_cross_site INT,
+ able_site_transfer INT,
+ is_allow_give INT,
+ is_allow_order_deduct INT,
+ is_delete INT,
+ bind_password TEXT,
+ goods_discount_range_type INT,
+ goodsCategoryId BIGINT,
+ tableAreaId BIGINT,
+ effect_site_id BIGINT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ disable_start_time TIMESTAMP,
+ disable_end_time TIMESTAMP,
+ last_consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ status INT,
+ sort INT,
+ tenantAvatar TEXT,
+ tenantName TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.member_stored_value_cards IS '对应JSON字段:member_stored_value_cards.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,与其他 JSON 中 tenant_id 一致。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenant_member_id IS '对应JSON字段:tenant_member_id,说明::当前商户(品牌/租户)中会员的主键 ID。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.system_member_id IS '对应JSON字段:system_member_id,说明::系统级会员 ID(跨门店统一主键)。,示例值及对应分析:枚举特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.register_site_id IS '对应JSON字段:register_site_id,说明::卡首次办理的门店 ID。,示例值及对应分析:对应门店的 site_id;本数据中所有卡都是在同一家门店开卡。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.site_name IS '对应JSON字段:site_name,说明::卡归属门店名称(视图中的展示字段)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.id IS '对应JSON字段:id,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code IS '对应JSON字段:member_card_grade_code,说明::卡等级/卡类代码,和下面两个名称字段一一对应。,示例值及对应分析:枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_grade_code_name IS '对应JSON字段:member_card_grade_code_name,说明::卡等级/卡类名称。,示例值及对应分析:枚举值(与上面 code 一一对应):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_card_type_name IS '对应JSON字段:member_card_type_name,说明::卡类型名称,实际与 member_card_grade_code_name 一致。,示例值及对应分析:枚举值同上。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_name IS '对应JSON字段:member_name,说明::持卡会员姓名快照。,示例值及对应分析:特点:存在 null(20 张卡没有绑定会员名字)。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.member_mobile IS '对应JSON字段:member_mobile,说明::持卡会员手机号快照。,示例值及对应分析:特点:与 member_name 对应,多数有值,少量为 null。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_type_id IS '对应JSON字段:card_type_id,说明::卡种 ID(定义“这是哪一种卡”)。,示例值及对应分析:枚举(按数据分布):';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_no IS '对应JSON字段:card_no,说明:(推测):实体卡物理卡号/条码号。当前这批卡看起来全部为“无物理卡号”(可能是全部虚拟卡或卡号隐藏不导出)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.card_physics_type IS '对应JSON字段:card_physics_type,说明::物理卡类型。,示例值及对应分析:当前数据:全部为 1。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.balance IS '对应JSON字段:balance,说明::当前卡内余额(主要针对储值卡、部分券卡)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.denomination IS '对应JSON字段:denomination,说明:(推测):面额/初始储值额度。,示例值及对应分析:本页数据未填充此字段;可能在分类型卡(如次卡/券)中才有意义,或者另有配置表。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount IS '对应JSON字段:table_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount IS '对应JSON字段:goods_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount IS '对应JSON字段:assistant_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount IS '对应JSON字段:assistant_reward_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_discount IS '对应JSON字段:table_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_discount IS '对应JSON字段:assistant_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_discount IS '对应JSON字段:coupon_discount,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_discount IS '对应JSON字段:goods_service_discount,说明::,示例值及对应分析:采用“几折”的记法:10=不打折,9=九折,8=八折。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_discount_sub_switch IS '对应JSON字段:assistant_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_discount_sub_switch IS '对应JSON字段:table_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_sub_switch IS '对应JSON字段:goods_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_discount_sub_switch IS '对应JSON字段:assistant_reward_discount_sub_switch,说明:(推测):“折扣是否叠加/替换其他折扣”的开关。,示例值及对应分析:可能枚举:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_service_deduct_radio IS '对应JSON字段:table_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_service_deduct_radio IS '对应JSON字段:assistant_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_service_deduct_radio IS '对应JSON字段:goods_service_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_deduct_radio IS '对应JSON字段:assistant_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.table_deduct_radio IS '对应JSON字段:table_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_deduct_radio IS '对应JSON字段:goods_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.coupon_deduct_radio IS '对应JSON字段:coupon_deduct_radio,说明::允许从该卡余额中抵扣的比例(百分比)。,示例值及对应分析:100.0 表示允许 100% 用卡余额支付该类消费;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistant_reward_deduct_radio IS '对应JSON字段:assistant_reward_deduct_radio,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableCardDeduct IS '对应JSON字段:tableCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableServiceCardDeduct IS '对应JSON字段:tableServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCarDeduct IS '对应JSON字段:goodsCarDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsServiceCardDeduct IS '对应JSON字段:goodsServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantCardDeduct IS '对应JSON字段:assistantCardDeduct,说明::针对台费/商品/助教三类消费的扣卡金额配置(类似“每小时从卡里扣 xx 元”或“每次抵扣 xx 元”的规则)。,示例值及对应分析:当前:所有为 0,说明在卡定义层面并没有指定固定扣卡金额,而是按照一般储值逻辑消费。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantServiceCardDeduct IS '对应JSON字段:assistantServiceCardDeduct,说明::如果系统中区分“储值金、服务金、奖励金”等子账户,这三个字段对应“服务金”子账户的扣款配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.assistantRewardCardDeduct IS '对应JSON字段:assistantRewardCardDeduct,说明::助教奖励金方向扣款的配置。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cardSettleDeduct IS '对应JSON字段:cardSettleDeduct,说明:已在扣卡规则部分说明,当前为 0。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.couponCardDeduct IS '对应JSON字段:couponCardDeduct,说明::与卡绑定的“券额度扣除配置”。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.deliveryFeeDeduct IS '对应JSON字段:deliveryFeeDeduct,说明::配送费可否/多少从卡中抵扣,目前无业务发生。,示例值及对应分析:综合来看:本门店的卡片在“规则配置层”预留了大量细粒度控制字段,但目前实际使用只体现在“balance”和“可用范围”,折扣和具体扣卡规则基本都未启用(全部保持默认值 10 折、100%比例、0 扣款),真正扣款逻辑在交易流水中体现。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.use_scene IS '对应JSON字段:use_scene,说明::卡使用场景说明(比如“仅店内使用”“仅团建”等),本门店尚未使用此字段。,示例值及对应分析:2. 会员信息与关联字段';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_cross_site IS '对应JSON字段:able_cross_site,说明::是否允许跨店使用。,示例值及对应分析:1:可以跨门店使用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_give IS '对应JSON字段:is_allow_give,说明::是否允许转赠/转让给其他会员。,示例值及对应分析:0:不允许;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_allow_order_deduct IS '对应JSON字段:is_allow_order_deduct,说明::是否允许在“订单层面统一扣款”。,示例值及对应分析:0:不允许(仅按项目扣卡);';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.bind_password IS '对应JSON字段:bind_password,说明::卡绑定密码,用于消费或查询验证(目前未启用)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goods_discount_range_type IS '对应JSON字段:goods_discount_range_type,说明:?????? member_stored_value_cards-Analysis.md,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tableAreaId IS '对应JSON字段:tableAreaId,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.effect_site_id IS '对应JSON字段:effect_site_id,说明:(推测):卡片限定生效门店 ID。,示例值及对应分析:为 0 时,配合 able_cross_site=1,可解释为“所有门店可用”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.start_time IS '对应JSON字段:start_time,说明::卡片生效开始时间(有效期起始)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.end_time IS '对应JSON字段:end_time,说明::卡片有效期结束时间。,示例值及对应分析:start_time / end_time 组合就是卡的有效期。不同卡种有效期配置不同,如储值卡长效、月卡固定一个月等。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_start_time IS '对应JSON字段:disable_start_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.disable_end_time IS '对应JSON字段:disable_end_time,说明::停用时间段(比如临时冻结卡的起止时间)。,示例值及对应分析:当前未启用,所有卡都是“未进入停用窗口”。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.last_consume_time IS '对应JSON字段:last_consume_time,说明::最近一次消费时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.create_time IS '对应JSON字段:create_time,说明::卡片创建时间(开卡时间)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.status IS '对应JSON字段:status,说明:(推测):,示例值及对应分析:1:正常可用;';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.sort IS '对应JSON字段:sort,说明::在前端展示或某些列表中的排序权重。,示例值及对应分析:具体取值分布不重要,主要反映展示优先级。';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantAvatar IS '对应JSON字段:tenantAvatar,说明::品牌头像 URL(未配置)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.tenantName IS '对应JSON字段:tenantName,说明::租户/品牌名称(当前导出为空)。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.pdAssisnatLevel IS '对应JSON字段:pdAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.cxAssisnatLevel IS '对应JSON字段:cxAssisnatLevel,说明:已上文说明:均为扩展限定维度,当前全部为空列表。,示例值及对应分析:?? member_stored_value_cards-Analysis.md';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.member_stored_value_cards.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.recharge_settlements (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.recharge_settlements IS '对应JSON字段:recharge_settlements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.id IS '对应JSON字段:id,说明::本条充值结算记录的主键 ID(唯一标识一条充值/撤销记录)。,示例值及对应分析:唯一性:74 条记录全部不同。';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantid IS '对应JSON字段:tenantid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.siteid IS '对应JSON字段:siteid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.sitename IS '对应JSON字段:sitename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.balanceamount IS '对应JSON字段:balanceamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cardamount IS '对应JSON字段:cardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.cashamount IS '对应JSON字段:cashamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponamount IS '对应JSON字段:couponamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.createtime IS '对应JSON字段:createtime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberid IS '对应JSON字段:memberid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membername IS '对应JSON字段:membername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberphone IS '对应JSON字段:memberphone,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tableid IS '对应JSON字段:tableid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.consumemoney IS '对应JSON字段:consumemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.onlineamount IS '对应JSON字段:onlineamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorid IS '对应JSON字段:operatorid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.operatorname IS '对应JSON字段:operatorname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revokeordername IS '对应JSON字段:revokeordername,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.revoketime IS '对应JSON字段:revoketime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payamount IS '对应JSON字段:payamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointamount IS '对应JSON字段:pointamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.refundamount IS '对应JSON字段:refundamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlename IS '对应JSON字段:settlename,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settlestatus IS '对应JSON字段:settlestatus,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.settletype IS '对应JSON字段:settletype,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paytime IS '对应JSON字段:paytime,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.roundingamount IS '对应JSON字段:roundingamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.adjustamount IS '对应JSON字段:adjustamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.servicemoney IS '对应JSON字段:servicemoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanname IS '对应JSON字段:salesmanname,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.orderremark IS '对应JSON字段:orderremark,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.canberevoked IS '对应JSON字段:canberevoked,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.serialnumber IS '对应JSON字段:serialnumber,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isusediscount IS '对应JSON字段:isusediscount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isactivity IS '对应JSON字段:isactivity,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isbindmember IS '对应JSON字段:isbindmember,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.isfirst IS '对应JSON字段:isfirst,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? recharge_settlements-Analysis.md,示例值及对应分析:?? recharge_settlements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.recharge_settlements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_records (
+ id BIGINT PRIMARY KEY,
+ tenantid BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ balanceamount NUMERIC(18,2),
+ cardamount NUMERIC(18,2),
+ cashamount NUMERIC(18,2),
+ couponamount NUMERIC(18,2),
+ createtime TIMESTAMPTZ,
+ memberid BIGINT,
+ membername TEXT,
+ tenantmembercardid BIGINT,
+ membercardtypename TEXT,
+ memberphone TEXT,
+ tableid BIGINT,
+ consumemoney NUMERIC(18,2),
+ onlineamount NUMERIC(18,2),
+ operatorid BIGINT,
+ operatorname TEXT,
+ revokeorderid BIGINT,
+ revokeordername TEXT,
+ revoketime TIMESTAMPTZ,
+ payamount NUMERIC(18,2),
+ pointamount NUMERIC(18,2),
+ refundamount NUMERIC(18,2),
+ settlename TEXT,
+ settlerelateid BIGINT,
+ settlestatus INT,
+ settletype INT,
+ paytime TIMESTAMPTZ,
+ roundingamount NUMERIC(18,2),
+ paymentmethod INT,
+ adjustamount NUMERIC(18,2),
+ assistantcxmoney NUMERIC(18,2),
+ assistantpdmoney NUMERIC(18,2),
+ couponsaleamount NUMERIC(18,2),
+ memberdiscountamount NUMERIC(18,2),
+ tablechargemoney NUMERIC(18,2),
+ goodsmoney NUMERIC(18,2),
+ realgoodsmoney NUMERIC(18,2),
+ servicemoney NUMERIC(18,2),
+ prepaymoney NUMERIC(18,2),
+ salesmanname TEXT,
+ orderremark TEXT,
+ salesmanuserid BIGINT,
+ canberevoked BOOLEAN,
+ pointdiscountprice NUMERIC(18,2),
+ pointdiscountcost NUMERIC(18,2),
+ activitydiscount NUMERIC(18,2),
+ serialnumber BIGINT,
+ assistantmanualdiscount NUMERIC(18,2),
+ allcoupondiscount NUMERIC(18,2),
+ goodspromotionmoney NUMERIC(18,2),
+ assistantpromotionmoney NUMERIC(18,2),
+ isusecoupon BOOLEAN,
+ isusediscount BOOLEAN,
+ isactivity BOOLEAN,
+ isbindmember BOOLEAN,
+ isfirst INT,
+ rechargecardamount NUMERIC(18,2),
+ giftcardamount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.settlement_records IS '对应JSON字段:settlement_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.id IS '对应JSON字段:id,说明::结账记录主键 ID(订单结算 ID)。,示例值及对应分析:结构关联:';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantid IS '对应JSON字段:tenantid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.siteid IS '对应JSON字段:siteid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.sitename IS '对应JSON字段:sitename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.balanceamount IS '对应JSON字段:balanceamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cardamount IS '对应JSON字段:cardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.cashamount IS '对应JSON字段:cashamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponamount IS '对应JSON字段:couponamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.createtime IS '对应JSON字段:createtime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberid IS '对应JSON字段:memberid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membername IS '对应JSON字段:membername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tenantmembercardid IS '对应JSON字段:tenantmembercardid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.membercardtypename IS '对应JSON字段:membercardtypename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberphone IS '对应JSON字段:memberphone,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tableid IS '对应JSON字段:tableid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.consumemoney IS '对应JSON字段:consumemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.onlineamount IS '对应JSON字段:onlineamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorid IS '对应JSON字段:operatorid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.operatorname IS '对应JSON字段:operatorname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeorderid IS '对应JSON字段:revokeorderid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revokeordername IS '对应JSON字段:revokeordername,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.revoketime IS '对应JSON字段:revoketime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.payamount IS '对应JSON字段:payamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointamount IS '对应JSON字段:pointamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.refundamount IS '对应JSON字段:refundamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlename IS '对应JSON字段:settlename,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlerelateid IS '对应JSON字段:settlerelateid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settlestatus IS '对应JSON字段:settlestatus,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.settletype IS '对应JSON字段:settletype,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paytime IS '对应JSON字段:paytime,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.roundingamount IS '对应JSON字段:roundingamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.paymentmethod IS '对应JSON字段:paymentmethod,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.adjustamount IS '对应JSON字段:adjustamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantcxmoney IS '对应JSON字段:assistantcxmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpdmoney IS '对应JSON字段:assistantpdmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.couponsaleamount IS '对应JSON字段:couponsaleamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.memberdiscountamount IS '对应JSON字段:memberdiscountamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.tablechargemoney IS '对应JSON字段:tablechargemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodsmoney IS '对应JSON字段:goodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.realgoodsmoney IS '对应JSON字段:realgoodsmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.servicemoney IS '对应JSON字段:servicemoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.prepaymoney IS '对应JSON字段:prepaymoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanname IS '对应JSON字段:salesmanname,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.orderremark IS '对应JSON字段:orderremark,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.salesmanuserid IS '对应JSON字段:salesmanuserid,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.canberevoked IS '对应JSON字段:canberevoked,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountprice IS '对应JSON字段:pointdiscountprice,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.pointdiscountcost IS '对应JSON字段:pointdiscountcost,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.activitydiscount IS '对应JSON字段:activitydiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.serialnumber IS '对应JSON字段:serialnumber,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantmanualdiscount IS '对应JSON字段:assistantmanualdiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.allcoupondiscount IS '对应JSON字段:allcoupondiscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.goodspromotionmoney IS '对应JSON字段:goodspromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.assistantpromotionmoney IS '对应JSON字段:assistantpromotionmoney,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusecoupon IS '对应JSON字段:isusecoupon,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isusediscount IS '对应JSON字段:isusediscount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isactivity IS '对应JSON字段:isactivity,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isbindmember IS '对应JSON字段:isbindmember,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.isfirst IS '对应JSON字段:isfirst,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.rechargecardamount IS '对应JSON字段:rechargecardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.giftcardamount IS '对应JSON字段:giftcardamount,说明:?????? settlement_records-Analysis.md,示例值及对应分析:?? settlement_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_cancellation_records (
+ id BIGINT PRIMARY KEY,
+ siteId BIGINT,
+ siteProfile JSONB,
+ assistantName TEXT,
+ assistantAbolishAmount NUMERIC(18,2),
+ assistantOn INT,
+ pdChargeMinutes INT,
+ tableAreaId BIGINT,
+ tableArea TEXT,
+ tableId BIGINT,
+ tableName TEXT,
+ trashReason TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_cancellation_records IS '对应JSON字段:assistant_cancellation_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.id IS '对应JSON字段:id,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteId IS '对应JSON字段:siteId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantName IS '对应JSON字段:assistantName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantAbolishAmount IS '对应JSON字段:assistantAbolishAmount,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.assistantOn IS '对应JSON字段:assistantOn,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.pdChargeMinutes IS '对应JSON字段:pdChargeMinutes,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableAreaId IS '对应JSON字段:tableAreaId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableArea IS '对应JSON字段:tableArea,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableId IS '对应JSON字段:tableId,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.tableName IS '对应JSON字段:tableName,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.trashReason IS '对应JSON字段:trashReason,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.createTime IS '对应JSON字段:createTime,说明:?????? assistant_cancellation_records-Analysis.md,示例值及对应分析:?? assistant_cancellation_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_cancellation_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_accounts_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ assistant_no TEXT,
+ nickname TEXT,
+ real_name TEXT,
+ mobile TEXT,
+ team_id BIGINT,
+ team_name TEXT,
+ user_id BIGINT,
+ level TEXT,
+ assistant_status INT,
+ work_status INT,
+ leave_status INT,
+ entry_time TIMESTAMP,
+ resign_time TIMESTAMP,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ order_trade_no TEXT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ system_role_id BIGINT,
+ avatar TEXT,
+ birth_date TIMESTAMP,
+ gender INT,
+ height NUMERIC(18,2),
+ weight NUMERIC(18,2),
+ job_num TEXT,
+ show_status INT,
+ show_sort INT,
+ sum_grade NUMERIC(18,2),
+ assistant_grade NUMERIC(18,2),
+ get_grade_times INT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ shop_name TEXT,
+ charge_way INT,
+ entry_type INT,
+ allow_cx INT,
+ is_guaranteed INT,
+ salary_grant_enabled INT,
+ light_status INT,
+ online_status INT,
+ is_delete INT,
+ cx_unit_price NUMERIC(18,2),
+ pd_unit_price NUMERIC(18,2),
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ person_org_id BIGINT,
+ serial_number BIGINT,
+ is_team_leader INT,
+ criticism_status INT,
+ last_update_name TEXT,
+ ding_talk_synced INT,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ entry_sign_status INT,
+ resign_sign_status INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.assistant_accounts_master IS '对应JSON字段:assistant_accounts_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.id IS '对应JSON字段:id,说明::助教账号主键 ID,在“助教流水.json”中对应 site_assistant_id。,示例值及对应分析:作用:所有与助教相关的事实表(助教流水、助教排班等)都会通过这个 ID 关联到该维表。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.tenant_id IS '对应JSON字段:tenant_id,说明::品牌/租户 ID,对应“非球科技”系统中该商户的唯一标识。,示例值及对应分析:用途:多门店时用来区分不同商户。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_id IS '对应JSON字段:site_id,说明::门店 ID,对应本次数据的这家球房(朗朗桌球)。,示例值及对应分析:关联:与其它 JSON(台费流水、库存、销售等)中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_no IS '对应JSON字段:assistant_no,说明:(结合字段名推测):助教工号 / 编号,便于业务侧识别。,示例值及对应分析:关联:在“助教流水.json”中有 assistantNo,与此字段对应。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.nickname IS '对应JSON字段:nickname,说明::助教在前台展示的昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:用途:与真实姓名区分,用于顾客侧展示。如在助教流水中 nickname 就是这个值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.real_name IS '对应JSON字段:real_name,说明::助教真实姓名,如“何海婷”“梁婷婷”等。,示例值及对应分析:关联:在“助教流水.json”的 assistantName 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.mobile IS '对应JSON字段:mobile,说明::助教手机号,用于登录绑定、通知、钉钉同步等。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_id IS '对应JSON字段:team_id,说明::助教所属团队 ID。,示例值及对应分析:关联:在“助教流水.json”中 assistant_team_id 与此一致。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.team_name IS '对应JSON字段:team_name,说明::团队名称,展示用,和 team_id 一一对应。,示例值及对应分析:group_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.level IS '对应JSON字段:level,说明:(结合“助教流水中的 assistant_level / levelName 推测”):,示例值及对应分析:8:助教管理/管理员(和流水里的 "助教管理" 对应)';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_status IS '对应JSON字段:assistant_status,说明:(推测):账号启用状态:,示例值及对应分析:1:启用';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.work_status IS '对应JSON字段:work_status,说明::,示例值及对应分析:1:在岗/可排班';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.leave_status IS '对应JSON字段:leave_status,说明:类型:int,枚举。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_time IS '对应JSON字段:entry_time,说明::入职时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_time IS '对应JSON字段:resign_time,说明::离职日期;使用“远未来日期”作为“未离职”的占位。,示例值及对应分析:entry_type';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.start_time IS '对应JSON字段:start_time,说明:(推测):当前配置生效的开始日期。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.end_time IS '对应JSON字段:end_time,说明::当前配置生效的结束日期(例如一个周期性的排班/合同周期)。,示例值及对应分析:last_table_id';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.create_time IS '对应JSON字段:create_time,说明::账号创建时间。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.update_time IS '对应JSON字段:update_time,说明::账号最近一次被修改的时间(例如修改等级、昵称等)。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.order_trade_no IS '对应JSON字段:order_trade_no,说明:(推测):该助教最近一次关联的订单号,用于快速跳转或回溯最近服务行为。,示例值及对应分析:9. 灯控、钉钉等系统集成相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_id IS '对应JSON字段:staff_id,说明:(推测):预留给“人事系统员工 ID”的字段,目前未接入或未启用。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.staff_profile_id IS '对应JSON字段:staff_profile_id,说明:(推测):人事档案 ID,与第三方 HR 系统或内部员工档案集成使用,当前未启用。,示例值及对应分析:4. 等级、计费与薪资配置字段';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.system_role_id IS '对应JSON字段:system_role_id,说明:?????? assistant_accounts_master-Analysis.md,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.avatar IS '对应JSON字段:avatar,说明::助教头像地址。,示例值及对应分析:introduce';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.gender IS '对应JSON字段:gender,说明:(结合常见约定与值分布推测):,示例值及对应分析:0:未填/保密';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_status IS '对应JSON字段:show_status,说明:(推测):前台展示状态:,示例值及对应分析:1:在助教选择界面展示。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.show_sort IS '对应JSON字段:show_sort,说明::前台展示排序权重,值越小/越大对应不同的排序策略(当前看起来与 assistant_no 有一定对应关系)。,示例值及对应分析:online_status';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.sum_grade IS '对应JSON字段:sum_grade,说明::评分总和,用于计算平均分(assistant_grade = sum_grade / get_grade_times),当前为 0。,示例值及对应分析:?? assistant_accounts_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.get_grade_times IS '对应JSON字段:get_grade_times,说明::累计被评分次数。,示例值及对应分析:charge_way';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.video_introduction_url IS '对应JSON字段:video_introduction_url,说明::助教个人视频介绍地址。,示例值及对应分析:height';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.user_id IS '对应JSON字段:user_id,说明:账号对应的用户 ID/员工 ID,用于跨表关联。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.height IS '对应JSON字段:height,说明:身高(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.weight IS '对应JSON字段:weight,说明:体重(数值),可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.job_num IS '对应JSON字段:job_num,说明:工号/岗位编号,保留原始取值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.assistant_grade IS '对应JSON字段:assistant_grade,说明:平均评分,通常 = sum_grade/get_grade_times。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.introduce IS '对应JSON字段:introduce,说明:个人简介/自我介绍,可空。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_id IS '对应JSON字段:group_id,说明:分组/自定义分组 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.group_name IS '对应JSON字段:group_name,说明:分组名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.shop_name IS '对应JSON字段:shop_name,说明:门店名称冗余。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.charge_way IS '对应JSON字段:charge_way,说明:收费方式枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_type IS '对应JSON字段:entry_type,说明:入职类型枚举,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.allow_cx IS '对应JSON字段:allow_cx,说明:是否允许超休/冲销(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_guaranteed IS '对应JSON字段:is_guaranteed,说明:是否保底(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.salary_grant_enabled IS '对应JSON字段:salary_grant_enabled,说明:薪资发放/补贴开关,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_status IS '对应JSON字段:light_status,说明:灯控状态/模式,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.online_status IS '对应JSON字段:online_status,说明:在线状态标记(0/1等)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_delete IS '对应JSON字段:is_delete,说明:逻辑删除标记(0=有效,1=删除)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.cx_unit_price IS '对应JSON字段:cx_unit_price,说明:超休单价/冲销单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.pd_unit_price IS '对应JSON字段:pd_unit_price,说明:排钟/点钟单价,金额类。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_id IS '对应JSON字段:last_table_id,说明:最近服务桌台 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.last_table_name IS '对应JSON字段:last_table_name,说明:最近服务桌台名称。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.person_org_id IS '对应JSON字段:person_org_id,说明:人员组织 ID/部门 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.serial_number IS '对应JSON字段:serial_number,说明:序列号/排序号,保留原值。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.is_team_leader IS '对应JSON字段:is_team_leader,说明:是否组长(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.criticism_status IS '对应JSON字段:criticism_status,说明:处罚/警告状态标记,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.ding_talk_synced IS '对应JSON字段:ding_talk_synced,说明:是否已同步钉钉(0/1)。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.site_light_cfg_id IS '对应JSON字段:site_light_cfg_id,说明:门店灯控配置 ID。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.light_equipment_id IS '对应JSON字段:light_equipment_id,说明:灯控设备 ID/硬件编号。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.entry_sign_status IS '对应JSON字段:entry_sign_status,说明:入职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.resign_sign_status IS '对应JSON字段:resign_sign_status,说明:离职签署状态,枚举。';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_accounts_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.assistant_service_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INT,
+ assistantName TEXT,
+ assistantNo TEXT,
+ assistant_level TEXT,
+ levelname TEXT,
+ site_assistant_id BIGINT,
+ skill_id BIGINT,
+ skillname TEXT,
+ system_member_id BIGINT,
+ tablename TEXT,
+ tenant_member_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ nickname TEXT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ manual_discount_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ projected_income NUMERIC(18,2),
+ real_use_seconds INT,
+ income_seconds INT,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ create_time TIMESTAMP,
+ is_single_order INT,
+ is_delete INT,
+ is_trash INT,
+ trash_reason TEXT,
+ trash_applicant_id BIGINT,
+ trash_applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ person_org_id BIGINT,
+ add_clock INT,
+ returns_clock INT,
+ composite_grade NUMERIC(10,2),
+ composite_grade_time TIMESTAMP,
+ skill_grade NUMERIC(10,2),
+ service_grade NUMERIC(10,2),
+ sum_grade NUMERIC(10,2),
+ grade_status INT,
+ get_grade_times INT,
+ is_not_responding INT,
+ is_confirm INT,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.assistant_service_records IS '对应JSON字段:assistant_service_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.id IS '对应JSON字段:id,说明::本条助教流水记录的主键 ID(流水唯一标识)。,示例值及对应分析:作用:在系统内部唯一定位这一条助教服务记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID;你这份数据中是固定值(同一个商户)。,示例值及对应分析:关联:全库所有表都有,作为“商户维度”的过滤键。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本数据中指“朗朗桌球”这一家门店。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,包括 id、shop_name、address 等,和其他 JSON 里的 siteProfile 一致。,示例值及对应分析:作用:冗余门店信息,方便查看(而不是每次都联表看门店档案)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::订单结算 ID,相当于“结账单号”的内部主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,整个订单层面的编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_pay_id IS '对应JSON字段:order_pay_id,说明::关联到“支付记录”的主键 ID。,示例值及对应分析:作用:可以和支付记录中的 id / relate_id 等字段对应,找到这条助教服务对应的支付流水。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_id IS '对应JSON字段:order_assistant_id,说明::订单中“助教项目明细”的内部 ID。,示例值及对应分析:作用:如果订单里有多条助教项目(比如换助教、多个时间段),此字段唯一标识这一条助教明细。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.order_assistant_type IS '对应JSON字段:order_assistant_type,说明:(推测):,示例值及对应分析:1:常规助教服务(主课/基础课)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantName IS '对应JSON字段:assistantName,说明::助教姓名,如“何海婷”“胡敏”等。,示例值及对应分析:备注:和助教账号档案里的 real_name 一致。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistantNo IS '对应JSON字段:assistantNo,说明::助教编号,例如 "27"。,示例值及对应分析:关联:在助教账号表里也有 assistant_no 字段,对应工号/编号。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_level IS '对应JSON字段:assistant_level,说明::助教等级名称,与 assistant_level 一一对应(初级/中级/高级/助教管理)。,示例值及对应分析:备注:属于展示用的冗余字段。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.assistant_team_id IS '对应JSON字段:assistant_team_id,说明::当前这条助教服务所对应的“课程/技能名称”。,示例值及对应分析:当 order_assistant_type = 1 时,多为“基础课”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.nickname IS '对应JSON字段:nickname,说明::助教对外昵称,如“佳怡”“周周”“球球”等。,示例值及对应分析:说明:从数据看,这个 nickname 是“助教昵称”,不是顾客昵称(容易混淆)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_name IS '对应JSON字段:ledger_name,说明:?????? assistant_service_records-Analysis.md,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):助教项目所属的“计费分组/套餐分组名称”,例如某种助教套餐或业务组名称。,示例值及对应分析:目前未被实际使用。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::按标准单价计算出来的应收金额(近似 = ledger_unit_price × income_seconds / 3600)。,示例值及对应分析:说明:从数据看,这个金额对应“按原价计费”的金额,未扣除各种优惠。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计时总秒数。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::助教服务 标准单价(通常是标价:每小时、每节课的单价)。,示例值及对应分析:特点:如 98.0、108.0、190.0 等。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):助教流水记录状态:,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账层面记录的开始时间。,示例值及对应分析:说明:与 start_use_time 在当前数据中完全一致,可以视为“计费起始时间”。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账层面的结束时间。,示例值及对应分析:说明:与 last_use_time 一致,可以视为“计费结束时间”。对于 real_use_seconds = 0 的记录,开始和结束时间相同,说明只是预约/录入,并未实际服务。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.manual_discount_amount IS '对应JSON字段:manual_discount_amount,说明::收银员手动给予的减免金额(人工改价)。,示例值及对应分析:当前导出时间段内暂未出现手动打折的情况。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员卡折扣产生的优惠金额。,示例值及对应分析:说明:尽管字段里是 0,但实际折扣可能已经体现在 projected_income 与 ledger_amount 的差额中,这里只是未单独拆出。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::由“优惠券/代金券/团购券”等 直接抵扣到这条助教服务上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_money IS '对应JSON字段:service_money,说明:(推测):用于记录与助教结算的金额(平台预留的“成本/分成”字段)。,示例值及对应分析:当前数据中未启用这个机制,所以全为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.projected_income IS '对应JSON字段:projected_income,说明::实际结算计入门店的金额(已经考虑折扣、卡权益、券等后的结果)。,示例值及对应分析:从数据:projected_income 明显低于 ledger_amount,说明中间有折扣,但折扣的明细并不全由下面几个字段体现(很多是卡权益内生折扣)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.real_use_seconds IS '对应JSON字段:real_use_seconds,说明::实际使用时长(秒)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.income_seconds IS '对应JSON字段:income_seconds,说明::计费秒数 / 应计收入对应的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.start_use_time IS '对应JSON字段:start_use_time,说明::助教实际开始服务时间。,示例值及对应分析:特点:正常情况下与 ledger_start_time 相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.last_use_time IS '对应JSON字段:last_use_time,说明::最后一次使用(实际服务)时间。,示例值及对应分析:特点:正常结束时与 ledger_end_time 相同;如果服务还未真正开始或立即结束,开始/结束时间可能相同。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.create_time IS '对应JSON字段:create_time,说明::这条助教流水记录创建时间(一般接近结算/下单时间)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独订单:,示例值及对应分析:1:本助教服务作为单独订单结算(或单独拆项)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_trash IS '对应JSON字段:is_trash,说明::是否已废除/作废:,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_reason IS '对应JSON字段:trash_reason,说明::废除原因(文本说明),例如“顾客取消”“录入错误”等。,示例值及对应分析:当前数据为空字符串,说明当前导出时间段没有被废除的助教流水记录。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_id IS '对应JSON字段:trash_applicant_id,说明::提出废除申请的员工 ID(通常是操作员/管理员)。,示例值及对应分析:当前数据全为 0,因此短期内没有发生废除操作。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.trash_applicant_name IS '对应JSON字段:trash_applicant_name,说明::废除申请人姓名。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入/结算这条助教服务的员工)。,示例值及对应分析:关联:可与员工/账号表对应(本次导出未单独给员工表,但其他 JSON 里多处出现该 ID)。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,与 operator_id 一起使用,便于直接阅读。,示例值及对应分析:user_id';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_name IS '对应JSON字段:salesman_name,说明::关联的“营业员/销售员姓名”,用于提成归属。,示例值及对应分析:观测:本数据中多数为空字符串,说明助教流水没有配置单独的营业员。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:观测:多为 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID。,示例值及对应分析:观测:多为 0,代表未指定。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.person_org_id IS '对应JSON字段:person_org_id,说明:同样在上文说明:助教所属人事组织 ID。,示例值及对应分析:9. 作废 / 废除相关字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.add_clock IS '对应JSON字段:add_clock,说明:(推测):加钟秒数,即在原有预约/服务基础上临时追加的时长。,示例值及对应分析:说明:值均为 60 的倍数(分钟级加钟),如 600 秒=10 分钟。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.returns_clock IS '对应JSON字段:returns_clock,说明:(推测):退钟秒数(取消加钟或提前结束退回的时间)。,示例值及对应分析:当前数据里没有退钟场景,所以全为 0,但字段设计已经预留。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade IS '对应JSON字段:composite_grade,说明::综合评分(例如技能+服务加权后的平均分),当前数据没有实际评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.composite_grade_time IS '对应JSON字段:composite_grade_time,说明:(推测):最近一次评价时间/综合评分更新时间。现在都是默认“无效时间”。,示例值及对应分析:3. 桌台 / 门店维度字段';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.skill_grade IS '对应JSON字段:skill_grade,说明:(推测):顾客对“技能表现”的评分(整数或打分等级)。,示例值及对应分析:当前数据中还未产生评分记录,所以都是默认值 0。';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.service_grade IS '对应JSON字段:service_grade,说明:(推测):顾客对“服务态度”的评分。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.sum_grade IS '对应JSON字段:sum_grade,说明::累计评分总和(可能用于计算平均分),当前为 0。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.grade_status IS '对应JSON字段:grade_status,说明:(推测):评价状态,比如:,示例值及对应分析:1 = 未评价/正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.get_grade_times IS '对应JSON字段:get_grade_times,说明::该条记录对应的评价次数(或该助教被评价次数快照)。,示例值及对应分析:?? assistant_service_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_not_responding IS '对应JSON字段:is_not_responding,说明:(推测):是否存在“爽约/未响应”情况:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.is_confirm IS '对应JSON字段:is_confirm,说明:(推测):确认状态,例如:,示例值及对应分析:1:待确认;';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.assistant_service_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.site_tables_master (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteName TEXT,
+ "appletQrCodeUrl" TEXT,
+ areaName TEXT,
+ audit_status INT,
+ charge_free INT,
+ create_time TIMESTAMP,
+ delay_lights_time INT,
+ is_online_reservation INT,
+ is_rest_area INT,
+ light_status INT,
+ only_allow_groupon INT,
+ order_delay_time INT,
+ self_table INT,
+ show_status INT,
+ site_table_area_id BIGINT,
+ tableStatusName TEXT,
+ table_cloth_use_Cycle INT,
+ table_cloth_use_time TIMESTAMP,
+ table_name TEXT,
+ table_price NUMERIC(18,2),
+ table_status INT,
+ temporary_light_second INT,
+ virtual_table INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.site_tables_master IS '对应JSON字段:site_tables_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.id IS '对应JSON字段:id,说明::台桌主键 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.siteName IS '对应JSON字段:siteName,说明::门店名称快照,冗余字段,配合 site_id 使用。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master."appletQrCodeUrl" IS '对应JSON字段:appletQrCodeUrl,说明::小程序二维码 URL。 一般用于:,示例值及对应分析:打印二维码贴在台上,顾客扫码可呼叫服务、查看账单或发起线上预约;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.areaName IS '对应JSON字段:areaName,说明::区域名称,用于前台展示和区域维度管理。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.audit_status IS '对应JSON字段:audit_status,说明:(结合命名惯例):,示例值及对应分析:2:已审核/已启用;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.charge_free IS '对应JSON字段:charge_free,说明:(推测):,示例值及对应分析:0:正常计费;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.create_time IS '对应JSON字段:create_time,说明::台桌配置的创建时间或最近一次创建/复制时间。,示例值及对应分析:三、与其它 JSON 的字段级关联关系(结构视角)';
+COMMENT ON COLUMN billiards_ods.site_tables_master.delay_lights_time IS '对应JSON字段:delay_lights_time,说明:(推测):台灯熄灭延迟时间(单位多半是秒或分钟),用于结账后延时关灯。,示例值及对应分析:本门店未启用延迟关灯功能(全部为 0)。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_online_reservation IS '对应JSON字段:is_online_reservation,说明:(结合值分布推断):,示例值及对应分析:1:允许线上预约(可在小程序/线上平台预约这张台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.is_rest_area IS '对应JSON字段:is_rest_area,说明:(推测):,示例值及对应分析:0:正常计费区域;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.light_status IS '对应JSON字段:light_status,说明:(结合命名推断):,示例值及对应分析:该字段是台灯/灯光状态开关位:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.only_allow_groupon IS '对应JSON字段:only_allow_groupon,说明:(结合命名推断):,示例值及对应分析:1:仅允许团购/券预约使用(团购专用台);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.order_delay_time IS '对应JSON字段:order_delay_time,说明:(推测):订单层面允许的“自动延时时长”(例如到点后自动延长多少时间继续计费)。,示例值及对应分析:本门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.self_table IS '对应JSON字段:self_table,说明:(推测):,示例值及对应分析:1:“本门店自有台”,非共享或外部配置;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.show_status IS '对应JSON字段:show_status,说明:(推测):,示例值及对应分析:1:正常在前台“开台列表”中展示;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店维度的“台桌区域 ID”。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.tableStatusName IS '对应JSON字段:tableStatusName,说明::table_status 的中文名称,仅为展示用途。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_Cycle IS '对应JSON字段:table_cloth_use_Cycle,说明:(推测):,示例值及对应分析:台呢使用周期阈值,例如达到某个秒数后提醒更换;';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_cloth_use_time IS '对应JSON字段:table_cloth_use_time,说明:(结合命名和数值特征):,示例值及对应分析:台呢使用累计时长,单位极大概率为“秒”:';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_name IS '对应JSON字段:table_name,说明::台号/台名称,用于前台操作界面展示,也出现在小票和各种流水中的 ledger_name 或 tableName 字段。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_price IS '对应JSON字段:table_price,说明:(结构角度):,示例值及对应分析:设计上应为“台的基础单价”字段(例如按小时或按局单价);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.table_status IS '对应JSON字段:table_status,说明::台当前运行状态,真实反映某一时刻台的占用/暂停情况。,示例值及对应分析:?? site_tables_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.site_tables_master.temporary_light_second IS '对应JSON字段:temporary_light_second,说明:(推测):临时点灯时长(秒),例如手动临时开灯一段时间。,示例值及对应分析:本门店未使用。';
+COMMENT ON COLUMN billiards_ods.site_tables_master.virtual_table IS '对应JSON字段:virtual_table,说明:(推测):,示例值及对应分析:0:物理台(实体存在的桌);';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.site_tables_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_discount_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ tableProfile JSONB,
+ tenant_table_area_id BIGINT,
+ adjust_type INT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_name TEXT,
+ ledger_status INT,
+ applicant_id BIGINT,
+ applicant_name TEXT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_discount_records IS '对应JSON字段:table_fee_discount_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.id IS '对应JSON字段:id,说明::台费打折 / 调整流水主键 ID。,示例值及对应分析:作用:在“台费调账表”中唯一标识一条折扣/调账操作。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:标识记录属于哪一个商户(同一个“非球科技”租户)。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,本批数据全部为同一家门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,用于报表时直接读取,无需再联门店档案。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.site_table_id IS '对应JSON字段:site_table_id,说明::台桌 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tableProfile IS '对应JSON字段:tableProfile,说明::折扣发生时,对应台桌的配置信息快照。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的“台桌区域 ID”。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.adjust_type IS '对应JSON字段:adjust_type,说明:(根据文件含义 + 命名 + 数据):,示例值及对应分析:文件名是“台费打折”,字段名为“调整类型”,当前所有记录都是 1,即“台费打折/台费减免”这一种调整类型。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_amount IS '对应JSON字段:ledger_amount,说明:(关键点):,示例值及对应分析:通过与 台费流水.json 做对比,可以明确:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_count IS '对应JSON字段:ledger_count,说明::,示例值及对应分析:这里不是“秒数”,而是“调整次数/条数”的量化,目前固定为 1,表示“一次调账事件”。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_name IS '对应JSON字段:ledger_name,说明:(推测):,示例值及对应分析:设计上应该用于记录“调账项目名称”或“打折原因描述”(例如某种优惠规则名称),但当前门店并未使用该字段。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.ledger_status IS '对应JSON字段:ledger_status,说明::,示例值及对应分析:1:生效调整(当前有效的台费打折 / 调账记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_id IS '对应JSON字段:applicant_id,说明::打折/调账申请人 ID。,示例值及对应分析:作用:记录谁发起了这次台费调整。 本时段内所有调整均由同一位员工发起。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.applicant_name IS '对应JSON字段:applicant_name,说明::申请人姓名(带角色描述),为 applicant_id 的冗余显示字段。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_id IS '对应JSON字段:operator_id,说明::实际执行调账操作的操作员 ID。,示例值及对应分析:说明:这段时间内,“申请人”和“操作员”是同一个人。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名。,示例值及对应分析:?? table_fee_discount_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单/小票 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.create_time IS '对应JSON字段:create_time,说明::台费调整记录的创建时间,即打折操作被执行的时间戳。,示例值及对应分析:说明:与台费流水中的 create_time(结算时间)相互配合,可以还原调整发生于结账之前还是之后。';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_discount_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.table_fee_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_pay_id BIGINT,
+ order_settle_id BIGINT,
+ ledger_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ ledger_start_time TIMESTAMP,
+ ledger_end_time TIMESTAMP,
+ start_use_time TIMESTAMP,
+ last_use_time TIMESTAMP,
+ real_table_use_seconds INT,
+ real_table_charge_money NUMERIC(18,2),
+ add_clock_seconds INT,
+ adjust_amount NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ used_card_amount NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ is_single_order INT,
+ is_delete INT,
+ member_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ salesman_name TEXT,
+ salesman_org_id BIGINT,
+ salesman_user_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.table_fee_transactions IS '对应JSON字段:table_fee_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.id IS '对应JSON字段:id,说明::台费流水记录主键(事实表主键)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。本文件所有记录都属于同一租户。,示例值及对应分析:关联:与所有其它 JSON 中的 tenant_id 一致,用于跨表做“商户维度”的过滤。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID,本次数据全部来自同一门店(朗朗桌球)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::当前门店的完整档案快照,冗余到流水表中,便于报表直接读取而无需再联表门店档案。,示例值及对应分析:三、与其它 JSON 的结构关联关系(从字段层面)';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_id IS '对应JSON字段:site_table_area_id,说明::门店内“台桌区域” ID(站在门店物理布局的角度)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.site_table_area_name IS '对应JSON字段:site_table_area_name,说明::台桌区域的名称,用于门店表现和区域统计。,示例值及对应分析:4. 会员维度与相关字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户维度的台桌区域 ID(品牌层面的同一类区域)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,是整笔订单的主编号。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_pay_id IS '对应JSON字段:order_pay_id,说明::订单支付记录 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单号/结账 ID,对应一次结账操作。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_name IS '对应JSON字段:ledger_name,说明::台号名称,实际展示给员工/顾客看的桌台编号。,示例值及对应分析:备注:与 site_table_id 一一对应,是桌台维表中的名称字段冗余到流水里的快照。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_amount IS '对应JSON字段:ledger_amount,说明::按单价与计费时长计算出的原始应收台费金额。,示例值及对应分析:近似关系:ledger_amount ≈ ledger_unit_price × ledger_count / 3600,考虑到四舍五入会有小数差。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_count IS '对应JSON字段:ledger_count,说明::台账记录的计费秒数,计费用秒数(应收时长)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::台费结算时设置的 每小时单价/计费单价。,示例值及对应分析:用途:与 ledger_count 共同决定原始应收额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):,示例值及对应分析:1:正常已结算台费;';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_start_time IS '对应JSON字段:ledger_start_time,说明::台账上的计费起始时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.ledger_end_time IS '对应JSON字段:ledger_end_time,说明::台账上的计费结束时间。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.start_use_time IS '对应JSON字段:start_use_time,说明::台开始使用的时间(实际开台时间)。,示例值及对应分析:特点:在数据中,与 ledger_start_time 完全相同(见下)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.last_use_time IS '对应JSON字段:last_use_time,说明::最后使用/操作时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_use_seconds IS '对应JSON字段:real_table_use_seconds,说明::实际使用的总秒数(系统真实统计的使用时长)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.real_table_charge_money IS '对应JSON字段:real_table_charge_money,说明::台费中实际向顾客收取的金额(现金/实付维度,未含券方承担或内部调账的那一部分)。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.add_clock_seconds IS '对应JSON字段:add_clock_seconds,说明::加钟秒数,在原有使用基础上追加的时长。,示例值及对应分析:观测:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.adjust_amount IS '对应JSON字段:adjust_amount,说明::调整金额/调账金额,用于将台费金额转移或冲减到其它项目,或手工调整。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.coupon_promotion_amount IS '对应JSON字段:coupon_promotion_amount,说明::由优惠券/活动/团购(平台/门店促销)承担的优惠金额,直接抵扣在台费上。,示例值及对应分析:特点:当 real_table_charge_money = 0 且该字段为 ledger_amount 时,说明整笔台费是由券促销全额承担。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_discount_amount IS '对应JSON字段:member_discount_amount,说明:上文已说明,这里补充与金额的结构关系:,示例值及对应分析:功能:表示由会员折扣或会员权益承担的那部分金额。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.used_card_amount IS '对应JSON字段:used_card_amount,说明::由储值卡、次卡等“卡内余额”抵扣的金额。,示例值及对应分析:说明:字段设计已预留,但本段时间内台费没有通过储值卡扣款,或者卡扣款在其他表体现。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.mgmt_fee IS '对应JSON字段:mgmt_fee,说明:(推测):管理费字段,用于未来支持“台费附加管理费/服务费”的功能。,示例值及对应分析:当前未启用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.service_money IS '对应JSON字段:service_money,说明:(推测):门店用于记录“服务费/成本/分成金额”的字段,类似助教流水里的 service_money。,示例值及对应分析:说明:当前门店未启用此字段结算台费。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fee_total IS '对应JSON字段:fee_total,说明::各种附加费用(如管理费、服务费)合计值。,示例值及对应分析:说明:和 mgmt_fee 一样,目前作为预留字段,没有实际使用。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):,示例值及对应分析:1:该台费记录对应的是一个独立计费单元(单独结算的桌费);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:未删除(有效记录);';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.member_id IS '对应JSON字段:member_id,说明::门店/租户内的会员 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID,负责开台/结账的员工账号 ID。,示例值及对应分析:关联:与员工/账号体系中的用户 ID 对应(与助教账号的 user_id 属于同一种 ID 体系)。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名(冗余字段),便于直接阅读,不必再联表员工档案。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_name IS '对应JSON字段:salesman_name,说明::业务员/营业员姓名,如果台费有单独提成员工,这里记录归属人。,示例值及对应分析:当前门店未启用该字段做提成归属。';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_org_id IS '对应JSON字段:salesman_org_id,说明::营业员所属机构/部门 ID。,示例值及对应分析:8. 状态 / 标记类字段';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员的用户 ID(与 salesman_name 搭配)。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.create_time IS '对应JSON字段:create_time,说明::这条台费流水记录的创建时间,通常接近结账时间。,示例值及对应分析:?? table_fee_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.table_fee_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_movements (
+ siteGoodsStockId BIGINT PRIMARY KEY,
+ tenantId BIGINT,
+ siteId BIGINT,
+ siteGoodsId BIGINT,
+ goodsName TEXT,
+ goodsCategoryId BIGINT,
+ goodsSecondCategoryId BIGINT,
+ unit TEXT,
+ price NUMERIC(18,4),
+ stockType INT,
+ changeNum NUMERIC(18,4),
+ startNum NUMERIC(18,4),
+ endNum NUMERIC(18,4),
+ changeNumA NUMERIC(18,4),
+ startNumA NUMERIC(18,4),
+ endNumA NUMERIC(18,4),
+ remark TEXT,
+ operatorName TEXT,
+ createTime TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_movements IS '对应JSON字段:goods_stock_movements.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsStockId IS '对应JSON字段:siteGoodsStockId,说明::门店某个“商品库存记录”的主键 ID。,示例值及对应分析:特点:每条库存变动记录对应一个 siteGoodsStockId,同一个商品可能在不同库存记录中出现(例如不同仓位或不同批次)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.tenantId IS '对应JSON字段:tenantId,说明::租户/品牌 ID。,示例值及对应分析:观测:全部记录相同值,说明属于同一商户。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:观测:本文件中所有记录的 siteId 都相同,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.siteGoodsId IS '对应JSON字段:siteGoodsId,说明::门店维度的商品 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsName IS '对应JSON字段:goodsName,说明::商品名称。,示例值及对应分析:示例值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明::商品一级分类 ID。,示例值及对应分析:观测:当前 100 条样本中约有 5 个不同 ID,对应如“酒水类”“食品小吃类”“香烟类”等大类(仅从命名与商品名推断)。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.goodsSecondCategoryId IS '对应JSON字段:goodsSecondCategoryId,说明::商品二级分类 ID。,示例值及对应分析:观测:样本中约有 7 个不同 ID,如饮料中的“矿泉水/功能饮料/碳酸饮料”等。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.unit IS '对应JSON字段:unit,说明::库存计量单位。,示例值及对应分析:说明:库存数量(startNum、endNum、changeNum)均以这里的单位计数。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.price IS '对应JSON字段:price,说明::商品单价(单位金额)。,示例值及对应分析:观测特征:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.stockType IS '对应JSON字段:stockType,说明:(基于数据行为推断):,示例值及对应分析:1:出库类变动 典型情况是销售出库,库存减少 1 或 2;例如顾客点了一瓶饮料,对应一条 stockType=1, changeNum=-1 的记录。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNum IS '对应JSON字段:changeNum,说明::本次库存数量变化值。,示例值及对应分析:特点及取值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNum IS '对应JSON字段:startNum,说明::变动前(这次出入库之前)的库存数量。,示例值及对应分析:示例: 如记录:startNum = 28, changeNum = -1, endNum = 27。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNum IS '对应JSON字段:endNum,说明::变动后(出入库之后)的库存数量。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.changeNumA IS '对应JSON字段:changeNumA,说明::辅助单位的变化量(与 changeNum 对应的第二计量单位变化),当前未使用。,示例值及对应分析:结论: startNumA / endNumA / changeNumA 是为“一个商品有两种计量单位(如箱与瓶)”而设计的预留字段。 目前门店只在单一单位层面管理库存,故全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.startNumA IS '对应JSON字段:startNumA,说明:(推测):辅助计量单位的起始库存(例如件/箱等第二单位)。,示例值及对应分析:当前门店在样本时间段内没有启用多单位库存管理,因此全部为 0。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.endNumA IS '对应JSON字段:endNumA,说明::辅助单位的变动后库存,同样未启用。,示例值及对应分析:?? goods_stock_movements-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.remark IS '对应JSON字段:remark,说明::备注信息,用于手工记录本次变更的特殊原因说明(例如“盘点差异调整”“报损”)。,示例值及对应分析:当前样本中没有填入任何备注,但字段已预留,适用于盘点或手工调整场景。';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.operatorName IS '对应JSON字段:operatorName,说明::执行此次库存变动的操作人。,示例值及对应分析:观测值:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.createTime IS '对应JSON字段:createTime,说明::这条库存变动记录的创建时间,即发生库存变更的时间点。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_movements.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.stock_goods_category_tree (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ category_name TEXT,
+ alias_name TEXT,
+ pid BIGINT,
+ business_name TEXT,
+ tenant_goods_business_id BIGINT,
+ open_salesman INT,
+ categoryBoxes JSONB,
+ sort INT,
+ is_warehousing INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.stock_goods_category_tree IS '对应JSON字段:stock_goods_category_tree.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.id IS '对应JSON字段:id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_id IS '对应JSON字段:tenant_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.category_name IS '对应JSON字段:category_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.alias_name IS '对应JSON字段:alias_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.pid IS '对应JSON字段:pid,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.business_name IS '对应JSON字段:business_name,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.open_salesman IS '对应JSON字段:open_salesman,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.categoryBoxes IS '对应JSON字段:categoryBoxes,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.sort IS '对应JSON字段:sort,说明:?????? stock_goods_category_tree-Analysis.md,示例值及对应分析:?? stock_goods_category_tree-Analysis.md';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.is_warehousing IS '对应JSON字段:is_warehousing,说明::分类节点主键 ID(在商品分类维度中的唯一标识)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.stock_goods_category_tree.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.goods_stock_summary (
+ siteGoodsId BIGINT PRIMARY KEY,
+ goodsName TEXT,
+ goodsUnit TEXT,
+ goodsCategoryId BIGINT,
+ goodsCategorySecondId BIGINT,
+ categoryName TEXT,
+ rangeStartStock NUMERIC(18,4),
+ rangeEndStock NUMERIC(18,4),
+ rangeIn NUMERIC(18,4),
+ rangeOut NUMERIC(18,4),
+ rangeSale NUMERIC(18,4),
+ rangeSaleMoney NUMERIC(18,2),
+ rangeInventory NUMERIC(18,4),
+ currentStock NUMERIC(18,4),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.goods_stock_summary IS '对应JSON字段:goods_stock_summary.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.siteGoodsId IS '对应JSON字段:siteGoodsId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsName IS '对应JSON字段:goodsName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsUnit IS '对应JSON字段:goodsUnit,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategoryId IS '对应JSON字段:goodsCategoryId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.goodsCategorySecondId IS '对应JSON字段:goodsCategorySecondId,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.categoryName IS '对应JSON字段:categoryName,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeStartStock IS '对应JSON字段:rangeStartStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeEndStock IS '对应JSON字段:rangeEndStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeIn IS '对应JSON字段:rangeIn,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeOut IS '对应JSON字段:rangeOut,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSale IS '对应JSON字段:rangeSale,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeSaleMoney IS '对应JSON字段:rangeSaleMoney,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.rangeInventory IS '对应JSON字段:rangeInventory,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.currentStock IS '对应JSON字段:currentStock,说明:?????? goods_stock_summary-Analysis.md,示例值及对应分析:?? goods_stock_summary-Analysis.md';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.goods_stock_summary.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.payment_transactions (
+ id BIGINT PRIMARY KEY,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ online_pay_channel INT,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.payment_transactions IS '对应JSON字段:payment_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.id IS '对应JSON字段:id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.site_id IS '对应JSON字段:site_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.siteProfile IS '对应JSON字段:siteProfile,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_type IS '对应JSON字段:relate_type,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.relate_id IS '对应JSON字段:relate_id,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_amount IS '对应JSON字段:pay_amount,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_status IS '对应JSON字段:pay_status,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.pay_time IS '对应JSON字段:pay_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.create_time IS '对应JSON字段:create_time,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payment_method IS '对应JSON字段:payment_method,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:?????? payment_transactions-Analysis.md,示例值及对应分析:?? payment_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.payment_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.refund_transactions (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ tenantName TEXT,
+ site_id BIGINT,
+ siteProfile JSONB,
+ relate_type INT,
+ relate_id BIGINT,
+ pay_sn TEXT,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ pay_status INT,
+ pay_time TIMESTAMP,
+ create_time TIMESTAMP,
+ payment_method INT,
+ pay_terminal INT,
+ pay_config_id BIGINT,
+ online_pay_channel INT,
+ online_pay_type INT,
+ channel_fee NUMERIC(18,2),
+ channel_payer_id TEXT,
+ channel_pay_no TEXT,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ cashier_point_id BIGINT,
+ operator_id BIGINT,
+ action_type INT,
+ check_status INT,
+ is_revoke INT,
+ is_delete INT,
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.refund_transactions IS '对应JSON字段:refund_transactions.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.id IS '对应JSON字段:id,说明::本条 退款流水 的唯一 ID。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID,全系统维度标识该商户。,示例值及对应分析:特点:本文件中所有记录相同。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.tenantName IS '对应JSON字段:tenantName,说明::租户(商户)名称。,示例值及对应分析:特点:本文件中固定为“朗朗桌球”,完全冗余于 siteProfile.shop_name。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:本文件中所有记录相同(单门店)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.siteProfile IS '对应JSON字段:siteProfile,说明::门店信息快照,结构与其他 JSON 中的 siteProfile 完全一致。包含字段包括但不限于:,示例值及对应分析:id:门店 ID(= site_id);';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_type IS '对应JSON字段:relate_type,说明::本退款对应的“业务类型”。,示例值及对应分析:结合支付记录的 relate_type 推测:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.relate_id IS '对应JSON字段:relate_id,说明::本次退款关联的业务 ID。,示例值及对应分析:对于 relate_type = 2:应该对应某个订单/结算的主键;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_sn IS '对应JSON字段:pay_sn,说明:?????? refund_transactions-Analysis.md,示例值及对应分析:?? refund_transactions-Analysis.md';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_amount IS '对应JSON字段:pay_amount,说明::本次退款的 资金变动金额。,示例值及对应分析:特征很重要:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.refund_amount IS '对应JSON字段:refund_amount,说明:(推测):,示例值及对应分析:设计上本应显示“实际退款金额”(正数),与 pay_amount 配合使用;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.round_amount IS '对应JSON字段:round_amount,说明:(推测):,示例值及对应分析:舍入金额/抹零金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_status IS '对应JSON字段:pay_status,说明:(推测):,示例值及对应分析:支付/退款状态枚举:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_time IS '对应JSON字段:pay_time,说明::退款在支付渠道层面实际发生的时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.create_time IS '对应JSON字段:create_time,说明::本条退款流水在系统内创建时间。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payment_method IS '对应JSON字段:payment_method,说明:(推测):,示例值及对应分析:支付/退款的 方式类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_terminal IS '对应JSON字段:pay_terminal,说明:(推测):,示例值及对应分析:退款所使用的 终端类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.pay_config_id IS '对应JSON字段:pay_config_id,说明:(推测):,示例值及对应分析:支付配置 ID,例如商户在“非球科技”内配置的某一条支付通道(某个微信商户号、银联通道)的主键。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_channel IS '对应JSON字段:online_pay_channel,说明:(推测):,示例值及对应分析:线上支付的 渠道编号,例如:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.online_pay_type IS '对应JSON字段:online_pay_type,说明:(推测):,示例值及对应分析:在线退款的类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_fee IS '对应JSON字段:channel_fee,说明:(推测):,示例值及对应分析:第三方支付渠道对本次退款收取的手续费;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_payer_id IS '对应JSON字段:channel_payer_id,说明:(推测):,示例值及对应分析:支付渠道侧的 payer ID,例如微信 openid、银行卡号掩码等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.channel_pay_no IS '对应JSON字段:channel_pay_no,说明:(推测):,示例值及对应分析:第三方支付平台的交易号(如微信支付单号、支付宝交易号等)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_id IS '对应JSON字段:member_id,说明::,示例值及对应分析:租户内部的会员 ID(对应会员档案中的某个主键)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.member_card_id IS '对应JSON字段:member_card_id,说明::,示例值及对应分析:关联的会员卡账户 ID(对应“储值卡列表”或“会员档案”中的某一张卡)。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.cashier_point_id IS '对应JSON字段:cashier_point_id,说明:(推测):,示例值及对应分析:收银点 ID,例如前台 1、前台 2、自助机等。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.operator_id IS '对应JSON字段:operator_id,说明::,示例值及对应分析:执行该退款操作的操作员 ID。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.action_type IS '对应JSON字段:action_type,说明:(推测):,示例值及对应分析:行为类型:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.check_status IS '对应JSON字段:check_status,说明:(推测):,示例值及对应分析:审核状态:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_revoke IS '对应JSON字段:is_revoke,说明:(推测):,示例值及对应分析:是否撤销型退款/撤销原支付:';
+COMMENT ON COLUMN billiards_ods.refund_transactions.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.balance_frozen_amount IS '对应JSON字段:balance_frozen_amount,说明:(推测):,示例值及对应分析:涉及会员储值卡退款时,暂时冻结的余额金额;';
+COMMENT ON COLUMN billiards_ods.refund_transactions.card_frozen_amount IS '对应JSON字段:card_frozen_amount,说明::与上一个类似,偏向“某张卡的被冻结金额”,也与会员卡/储值账户相关。,示例值及对应分析:状态同上:本数据中未发生“卡冻结退款”。';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.refund_transactions.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.platform_coupon_redemption_records (
+ id BIGINT PRIMARY KEY,
+ verify_id BIGINT,
+ certificate_id TEXT,
+ coupon_code TEXT,
+ coupon_name TEXT,
+ coupon_channel INT,
+ groupon_type INT,
+ group_package_id BIGINT,
+ sale_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ coupon_free_time NUMERIC(18,2),
+ coupon_cover TEXT,
+ coupon_remark TEXT,
+ use_status INT,
+ consume_time TIMESTAMP,
+ create_time TIMESTAMP,
+ deal_id TEXT,
+ channel_deal_id TEXT,
+ site_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ tenant_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_delete INT,
+ siteProfile JSONB,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.platform_coupon_redemption_records IS '对应JSON字段:platform_coupon_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.id IS '对应JSON字段:id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.verify_id IS '对应JSON字段:verify_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.certificate_id IS '对应JSON字段:certificate_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_name IS '对应JSON字段:coupon_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_channel IS '对应JSON字段:coupon_channel,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.groupon_type IS '对应JSON字段:groupon_type,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.group_package_id IS '对应JSON字段:group_package_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.sale_price IS '对应JSON字段:sale_price,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_free_time IS '对应JSON字段:coupon_free_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_cover IS '对应JSON字段:coupon_cover,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.coupon_remark IS '对应JSON字段:coupon_remark,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.use_status IS '对应JSON字段:use_status,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.consume_time IS '对应JSON字段:consume_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.create_time IS '对应JSON字段:create_time,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.deal_id IS '对应JSON字段:deal_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.channel_deal_id IS '对应JSON字段:channel_deal_id,说明:任意一个 ID 字段缺失时(如部分记录 deal_id=0),仍然可以通过其他字段(coupon_name + sale_price + coupon_money + channel_deal_id)唯一识别该产品。,示例值及对应分析:这种多字段冗余,结构上提升了抗“配置缺失”的能力。';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_id IS '对应JSON字段:site_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.site_order_id IS '对应JSON字段:site_order_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.table_id IS '对应JSON字段:table_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_id IS '对应JSON字段:operator_id,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.operator_name IS '对应JSON字段:operator_name,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.is_delete IS '对应JSON字段:is_delete,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.siteProfile IS '对应JSON字段:siteProfile,说明:?????? platform_coupon_redemption_records-Analysis.md,示例值及对应分析:?? platform_coupon_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.platform_coupon_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.tenant_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ categoryName TEXT,
+ unit TEXT,
+ goods_number TEXT,
+ out_goods_id TEXT,
+ goods_state INT,
+ sale_channel INT,
+ able_discount INT,
+ able_site_transfer INT,
+ is_delete INT,
+ is_warehousing INT,
+ isInSite INT,
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ market_price NUMERIC(18,4),
+ min_discount_price NUMERIC(18,4),
+ common_sale_royalty NUMERIC(18,4),
+ point_sale_royalty NUMERIC(18,4),
+ pinyin_initial TEXT,
+ commodityCode TEXT,
+ commodity_code TEXT,
+ goods_cover TEXT,
+ supplier_id BIGINT,
+ remark_name TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.tenant_goods_master IS '对应JSON字段:tenant_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 tenant_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.id IS '对应JSON字段:id,说明::商品档案主键 ID,唯一标识一条商品。,示例值及对应分析:作用:作为其他业务表(销售明细、库存流水、门店商品表等)的外键,通常以 tenant_goods_id 或类似字段出现。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:作用:和其它 JSON 中的 tenant_id / tenantId 一致,用于区分不同商户(本次数据只包含同一租户)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称(前台展示名称)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条码(EAN 等),目前未维护。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.categoryName IS '对应JSON字段:categoryName,说明::商品一级分类名称(业务可读)。,示例值及对应分析:取值情况:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.unit IS '对应JSON字段:unit,说明::计量单位。,示例值及对应分析:取值(共 12 种左右):';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_number IS '对应JSON字段:goods_number,说明::商品内部编码(自定义货号/系统货号)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_state IS '对应JSON字段:goods_state,说明:(推测):商品状态(上架/下架等)。,示例值及对应分析:1:正常/上架;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明:(推测):销售渠道类型,如“门店堂食/线下零售/线上小程序”等的一种编码。,示例值及对应分析:现有数据只有一个值,说明本门店目前仅通过一种渠道销售这些商品。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(推测):是否允许参与折扣/打折。,示例值及对应分析:1:允许折扣;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(推测):,示例值及对应分析:字面意思是“是否允许门店间调拨/门店级操作”:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效商品);';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明:(推测):是否启用库存管理。,示例值及对应分析:1:该商品纳入库存管理;';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.isInSite IS '对应JSON字段:isInSite,说明:(从命名推测):是否在当前门店启用/上架。,示例值及对应分析:现象:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price IS '对应JSON字段:cost_price,说明::成本价格。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(推测):,示例值及对应分析:不同的成本价格来源或计算方式,如:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.market_price IS '对应JSON字段:market_price,说明::商品标价 / 售价(标准销售单价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::该商品允许售卖的最低价格(底价)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.common_sale_royalty IS '对应JSON字段:common_sale_royalty,说明:(推测):普通销售提成比例或提成金额的配置字段。,示例值及对应分析:当前门店未在商品档案上配置员工提成规则,全部为 0。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.point_sale_royalty IS '对应JSON字段:point_sale_royalty,说明:(推测):积分销售提成/积分赠送规则相关配置。,示例值及对应分析:当前同样未启用。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::拼音首字母/助记码。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodityCode IS '对应JSON字段:commodityCode,说明::,示例值及对应分析:与 commodity_code 是同一信息的数组形式(冗余存储),便于支持一个商品对应多个编码的场景。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.commodity_code IS '对应JSON字段:commodity_code,说明::商品编码(通常为对外商品编码或条码)。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品封面图片 URL 地址。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.supplier_id IS '对应JSON字段:supplier_id,说明::供应商 ID,用于关联到供应商档案。,示例值及对应分析:当前所有商品都未挂接具体供应商(或门店未使用供应链管理模块)。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.remark_name IS '对应JSON字段:remark_name,说明:(从命名推断):商品备注名/别名,通常用来配置简写或特殊显示名称。,示例值及对应分析:当前门店尚未使用该字段,字段设计为将来扩展预留。';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.create_time IS '对应JSON字段:create_time,说明::商品档案创建时间。,示例值及对应分析:特征:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.update_time IS '对应JSON字段:update_time,说明::商品档案最近一次修改时间。,示例值及对应分析:分布:';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.tenant_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_packages (
+ id BIGINT PRIMARY KEY,
+ package_id BIGINT,
+ package_name TEXT,
+ selling_price NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ date_type INT,
+ date_info TEXT,
+ start_time TIMESTAMP,
+ end_time TIMESTAMP,
+ start_clock TEXT,
+ end_clock TEXT,
+ add_start_clock TEXT,
+ add_end_clock TEXT,
+ duration INT,
+ usable_count INT,
+ usable_range INT,
+ table_area_id BIGINT,
+ table_area_name TEXT,
+ table_area_id_list JSONB,
+ tenant_table_area_id BIGINT,
+ tenant_table_area_id_list JSONB,
+ site_id BIGINT,
+ site_name TEXT,
+ tenant_id BIGINT,
+ card_type_ids JSONB,
+ group_type INT,
+ system_group_type INT,
+ type INT,
+ effective_status INT,
+ is_enabled INT,
+ is_delete INT,
+ max_selectable_categories INT,
+ area_tag_type INT,
+ creator_name TEXT,
+ create_time TIMESTAMP,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now(),
+ payload JSONB NOT NULL
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_packages IS '对应JSON字段:group_buy_packages.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.id IS '对应JSON字段:id,说明::门店侧套餐 ID,本文件内部的主键。,示例值及对应分析:特点:17 条记录中均为不同的大整数 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_id IS '对应JSON字段:package_id,说明::“上层套餐 ID” 或“总部/系统级套餐 ID”。,示例值及对应分析:特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.package_name IS '对应JSON字段:package_name,说明::团购套餐名称,用于前台展示和核销界面。,示例值及对应分析:示例:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.selling_price IS '对应JSON字段:selling_price,说明:(结合字段命名):,示例值及对应分析:语义上应该是“团购售卖价”(顾客在平台购买券时的成交价格)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.coupon_money IS '对应JSON字段:coupon_money,说明::券面值或内部结算面值,表示该套餐在门店侧对应的金额额度。,示例值及对应分析:示例(对应套餐名称):';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_type IS '对应JSON字段:date_type,说明:(推测):,示例值及对应分析:典型用法:区分“全部日期可用 / 工作日 / 周末 / 指定日期”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.date_info IS '对应JSON字段:date_info,说明:(推测):,示例值及对应分析:预留字段,通常用来存储更细粒度的日期信息,如具体日期列表、节假日特殊规则(可能是 JSON 字符串或编码)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_time IS '对应JSON字段:start_time,说明::套餐开始生效的日期时间。,示例值及对应分析:示例:"2025-07-20 00:00:00" 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_time IS '对应JSON字段:end_time,说明::套餐失效的日期时间(到这个时间点后不可使用)。,示例值及对应分析:示例:形如 "2025-11-30 23:59:59",部分记录使用 9999-12-31 23:59:59 风格的极大日期表示长期有效(本数据中如有这种值,可解读为“长期有效”)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.start_clock IS '对应JSON字段:start_clock,说明::每日可用起始时间点(第一段)。,示例值及对应分析:说明:配合 end_clock 使用,定义一个日内时段。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.end_clock IS '对应JSON字段:end_clock,说明::每日可用的结束时间点(第一段)。,示例值及对应分析:结构说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_start_clock IS '对应JSON字段:add_start_clock,说明:(推测):附加可用时间段的起始时间(第二段)。,示例值及对应分析:例如有的套餐可以在两个不连续的时段使用:早场 + 夜场,则可用第一段 start_clock / end_clock 和第二段 add_start_clock / add_end_clock 组合。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.add_end_clock IS '对应JSON字段:add_end_clock,说明::附加时段结束时间,多数情况配合 "00:00:00" 或 "10:00:00" 使用。,示例值及对应分析:整体理解:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.duration IS '对应JSON字段:duration,说明::套餐内包含的时长(秒)。,示例值及对应分析:与名称一致:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_count IS '对应JSON字段:usable_count,说明::可使用次数上限。,示例值及对应分析:数据特征说明:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.usable_range IS '对应JSON字段:usable_range,说明:吻合(A区中八/B区中八/斯诺克/KTV/包厢等)。,示例值及对应分析:通过该关联,系统在核销时可以校验:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id IS '对应JSON字段:table_area_id,说明:(推测):,示例值及对应分析:原始设计应为“单一台区 ID”,当套餐只限一个区域可以用这个字段存储。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_name IS '对应JSON字段:table_area_name,说明::套餐适用的“门店台区名称”,用于显示和筛选。,示例值及对应分析:说明:这个字段是对区域 ID 维度的文字描述,便于直观理解。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.table_area_id_list IS '对应JSON字段:table_area_id_list,说明:(推测):,示例值及对应分析:用来存放具体台区 ID 列表(例如 "1,2,3"),实现更细粒度的台桌限制。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明:(推测):,示例值及对应分析:与 table_area_id 类似,是租户层级的台区 ID,原本用于单区选择。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_table_area_id_list IS '对应JSON字段:tenant_table_area_id_list,说明:(推测):,示例值及对应分析:实际代表“台区集合 ID”或“租户台区配置 ID”,用来限制套餐可用的台区范围。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:特点:全表值相同,且与其他 JSON 文件中的 site_id 一致,对应“朗朗桌球”这家门店。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.site_name IS '对应JSON字段:site_name,说明::门店名称。,示例值及对应分析:观测值:全部为 "朗朗桌球"。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.tenant_id IS '对应JSON字段:tenant_id,说明::租户 ID(品牌/商户 ID)。,示例值及对应分析:特点:全表值相同,说明所有套餐定义属于同一商户(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.card_type_ids IS '对应JSON字段:card_type_ids,说明:(推测):,示例值及对应分析:原意是“适用会员卡类型 ID 列表”,例如某套餐只允许某几种会员卡使用,可以在此配置。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.group_type IS '对应JSON字段:group_type,说明:(推测):,示例值及对应分析:团购类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.system_group_type IS '对应JSON字段:system_group_type,说明:(推测):,示例值及对应分析:系统内对团购类型更底层的划分,比如:';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.type IS '对应JSON字段:type,说明:(推测):,示例值及对应分析:内部业务子类型,具体含义需要结合系统文档;仅从数据无法确定是“台费类 vs 包厢类”还是“平台套餐 vs 自定义套餐”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.effective_status IS '对应JSON字段:effective_status,说明:(结合命名和数据特征推断):,示例值及对应分析:1:有效(在当前时间区间内、配置正常,可核销使用)。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_enabled IS '对应JSON字段:is_enabled,说明::启用状态。,示例值及对应分析:从其他表的统一风格来看,1 一般表示“启用 / 上架”,2 表示“停用 / 下架”。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.max_selectable_categories IS '对应JSON字段:max_selectable_categories,说明:?????? group_buy_packages-Analysis.md,示例值及对应分析:?? group_buy_packages-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.area_tag_type IS '对应JSON字段:area_tag_type,说明:(推测):区域标记类型:,示例值及对应分析:1 很可能代表“按台区标签限制”,例如 A区、中八区、包厢、KTV 等。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.creator_name IS '对应JSON字段:creator_name,说明::创建人信息,一般包含“角色:姓名”。,示例值及对应分析:示例:"管理员:郑丽珊"';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.create_time IS '对应JSON字段:create_time,说明::该套餐在系统中创建的时间。,示例值及对应分析:特点:每条记录各不相同,覆盖了 2025-07 至 2025-10 的创建时间。';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_packages.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.group_buy_redemption_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ table_id BIGINT,
+ tableName TEXT,
+ tableAreaName TEXT,
+ tenant_table_area_id BIGINT,
+ order_trade_no TEXT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ order_coupon_channel INT,
+ coupon_code TEXT,
+ coupon_money NUMERIC(18,2),
+ coupon_origin_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ table_charge_seconds INT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ promotion_seconds INT,
+ offer_type INT,
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ goodsOptionPrice NUMERIC(18,2),
+ salesman_name TEXT,
+ sales_man_org_id BIGINT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ is_single_order INT,
+ is_delete INT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.group_buy_redemption_records IS '对应JSON字段:group_buy_redemption_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.id IS '对应JSON字段:id,说明::本条“团购套餐流水”记录的 主键 ID。,示例值及对应分析:作用:唯一标识一条券使用到台费上的记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特点:全表值相同,说明所有记录属于同一租户。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.site_id IS '对应JSON字段:site_id,说明::门店 ID,与其它 JSON 中一致。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.siteName IS '对应JSON字段:siteName,说明::门店名称,冗余展示用。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_id IS '对应JSON字段:table_id,说明::球台 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableName IS '对应JSON字段:tableName,说明::本次使用券所关联的 球台名称/台号。,示例值及对应分析:关联:对应台桌列表中的 table_name / table_no,通过 table_id 进一步关联。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tableAreaName IS '对应JSON字段:tableAreaName,说明::该球台所属的 台区名称。,示例值及对应分析:关联:与台区配置中的 area_name 含义一致,与团购套餐定义中的 table_area_name 一致。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.tenant_table_area_id IS '对应JSON字段:tenant_table_area_id,说明::租户级台区分组 ID,表示当前使用券的台桌所属的区域组合。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_trade_no IS '对应JSON字段:order_trade_no,说明::订单交易号,和其它消费明细(台费、商品、助教、团购)共用的订单主键。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_settle_id IS '对应JSON字段:order_settle_id,说明::结算单 ID(小票结账主键)。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:(推测):,示例值及对应分析:指向支付记录表中的支付流水 ID。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单中“券使用记录”的 ID。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.order_coupon_channel IS '对应JSON字段:order_coupon_channel,说明:(推测):,示例值及对应分析:券渠道类型,例如:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_code IS '对应JSON字段:coupon_code,说明::团购券券码,核销时扫描/录入的字符串。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_money IS '对应JSON字段:coupon_money,说明::本次核销时,这张券在门店侧对应的金额额度(“可抵扣金额”)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.coupon_origin_id IS '对应JSON字段:coupon_origin_id,说明:(推测):,示例值及对应分析:平台/上游系统中的券记录主键 ID,“券来源 ID”。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_name IS '对应JSON字段:ledger_name,说明::台费侧关联的“团购项目名称”(记账名)。,示例值及对应分析:结构上通常来源于团购套餐定义的 package_name,或由系统在创建活动时生成。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明:(推测):团购项目所属的“记账分组名称”(例如“团购台费”“团购包厢”等)。,示例值及对应分析:当前门店未对团购项目做进一步分组。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::本次券实际冲抵台费的金额。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_count IS '对应JSON字段:ledger_count,说明::按此次优惠实际计算的“核销秒数”。,示例值及对应分析:结构观察:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::对应台费的标准单价,单位元/小时(从数值来看是类似29.9/小时这种定价)。,示例值及对应分析:作用:配合 ledger_count 用于计算这一条券在台费层面对应的金额(理论上应接近 = 单价 × 秒数/3600)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.ledger_status IS '对应JSON字段:ledger_status,说明:(推测):流水状态。,示例值及对应分析:1:正常有效;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_charge_seconds IS '对应JSON字段:table_charge_seconds,说明::本次结算中该球台总计计费的秒数(整台的台费计费时间)。,示例值及对应分析:结构特点:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_activity_id IS '对应JSON字段:promotion_activity_id,说明:(推测):团购/促销活动 ID。,示例值及对应分析:对应平台或内部促销活动的主键,每个活动通常绑定一个或多个具体套餐(promotion_coupon_id)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_coupon_id IS '对应JSON字段:promotion_coupon_id,说明::团购套餐定义 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.promotion_seconds IS '对应JSON字段:promotion_seconds,说明::团购套餐定义的“标准时长”(券本身标称的可用时长)。,示例值及对应分析:结构关系:';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.offer_type IS '对应JSON字段:offer_type,说明:(推测):优惠类型。,示例值及对应分析:在券适用多个优惠方式的系统中,一般用来区分“满减/折扣/代金券/套餐券”等。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_promotion_money IS '对应JSON字段:assistant_promotion_money,说明::分摊到“助教服务”的促销金额。,示例值及对应分析:当前场景下,团购券只与台费相关,未涉及助教的金额抵扣。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.assistant_service_promotion_money IS '对应JSON字段:assistant_service_promotion_money,说明::进一步细分助教服务的促销金额。,示例值及对应分析:当前未使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.table_service_promotion_money IS '对应JSON字段:table_service_promotion_money,说明::本次券使用中,分摊到“台费服务费”部分的促销金额。,示例值及对应分析:当前样本中,促销金额都在 ledger_amount 中体现,该字段未单独拆出。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goods_promotion_money IS '对应JSON字段:goods_promotion_money,说明::本次券使用中,分摊到“商品”部分的促销金额。,示例值及对应分析:当前数据中,所有团购券都只用于抵扣台费,没有用来抵扣商品,因此该字段为 0。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.recharge_promotion_money IS '对应JSON字段:recharge_promotion_money,说明::来自“充值类优惠”的分摊金额(例如储值赠送部分)。,示例值及对应分析:当前所有数据为 0,但结构上已经预留了“多来源促销金额分摊”的能力。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.reward_promotion_money IS '对应JSON字段:reward_promotion_money,说明::本次促销中,属于“奖励金/积分抵扣”的金额。,示例值及对应分析:当前没有使用此维度的促销。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.goodsOptionPrice IS '对应JSON字段:goodsOptionPrice,说明:(按命名推测):商品规格价格,用于商品类促销分摊时使用。,示例值及对应分析:当前在“团购套餐流水”中未被实际使用。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织 ID。,示例值及对应分析:以上 4 个销售相关字段在当前门店的团购套餐使用中都未启用,仅作为结构预留。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员角色 ID。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员/业务员用户 ID。,示例值及对应分析:当前所有团购套餐流水都未指定独立的营业员。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_id IS '对应JSON字段:operator_id,说明::执行本次核销/结算操作的 操作员 ID。,示例值及对应分析:关联:可以与员工档案表中的 id 对应(当前导出中员工表未单独给出,但风格和其它表一致)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.operator_name IS '对应JSON字段:operator_name,说明::操作员名称(包含角色说明),与 operator_id 对应的冗余展示字段。,示例值及对应分析:?? group_buy_redemption_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_single_order IS '对应JSON字段:is_single_order,说明:(推测):是否单独作为一条订单行。,示例值及对应分析:1:以独立条目方式进行结算(绝大部分记录如此)。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志:,示例值及对应分析:0:正常;';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.create_time IS '对应JSON字段:create_time,说明::本条团购套餐使用流水创建时间(即券核销时间,或与结账时间接近)。,示例值及对应分析:用法:可用于按时间范围过滤团购使用记录。';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.group_buy_redemption_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.settlement_ticket_details (
+ orderSettleId BIGINT PRIMARY KEY,
+ actualPayment NUMERIC(18,2),
+ adjustAmount NUMERIC(18,2),
+ assistantManualDiscount NUMERIC(18,2),
+ balanceAmount NUMERIC(18,2),
+ cashierName TEXT,
+ consumeMoney NUMERIC(18,2),
+ couponAmount NUMERIC(18,2),
+ deliveryAddress TEXT,
+ deliveryFee NUMERIC(18,2),
+ ledgerAmount NUMERIC(18,2),
+ memberDeductAmount NUMERIC(18,2),
+ memberOfferAmount NUMERIC(18,2),
+ onlineReturnAmount NUMERIC(18,2),
+ orderRemark TEXT,
+ orderSettleNumber BIGINT,
+ payMemberBalance NUMERIC(18,2),
+ payTime TIMESTAMP,
+ paymentMethod INT,
+ pointDiscountCost NUMERIC(18,2),
+ pointDiscountPrice NUMERIC(18,2),
+ prepayMoney NUMERIC(18,2),
+ refundAmount NUMERIC(18,2),
+ returnGoodsAmount NUMERIC(18,2),
+ rewardName TEXT,
+ settleType TEXT,
+ siteAddress TEXT,
+ siteBusinessTel TEXT,
+ siteId BIGINT,
+ siteName TEXT,
+ tenantId BIGINT,
+ tenantName TEXT,
+ ticketCustomContent TEXT,
+ ticketRemark TEXT,
+ voucherMoney NUMERIC(18,2),
+ memberProfile JSONB,
+ orderItem JSONB,
+ tenantMemberCardLogs JSONB,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.settlement_ticket_details IS '对应JSON字段:settlement_ticket_details.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleId IS '对应JSON字段:orderSettleId,说明::同 data.data.orderSettleId,为结算单 ID 的冗余。,示例值及对应分析:orderType';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.actualPayment IS '对应JSON字段:actualPayment,说明::本单实际支付金额总和(顾客本次实际付出:现金 + 线上 + 会员余额等)。,示例值及对应分析:一般应与支付记录中各支付流水金额汇总相匹配。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.adjustAmount IS '对应JSON字段:adjustAmount,说明::台费层面的人工调价金额(仅台费部分)。,示例值及对应分析:memberDiscountAmount';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.assistantManualDiscount IS '对应JSON字段:assistantManualDiscount,说明::针对“助教项目”的人工减免金额汇总(整单维度)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.balanceAmount IS '对应JSON字段:balanceAmount,说明::本单通过“会员余额/储值卡”支付的金额(从余额中扣除的总额)。,示例值及对应分析:对应 结账记录.json 的同名字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.cashierName IS '对应JSON字段:cashierName,说明::本单结算操作员名称(带角色前缀文字)。,示例值及对应分析:对应员工维表中的某个账号,便于小票上展示“收银员:XXX”。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.consumeMoney IS '对应JSON字段:consumeMoney,说明::本单“消费金额总计”(原价层面),即台费 + 商品 + 助教 + 服务等消费项目的金额总和(未扣除各类优惠)。,示例值及对应分析:对应 结账记录.json 的 consumeMoney 字段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.couponAmount IS '对应JSON字段:couponAmount,说明::本单由优惠券抵扣的金额汇总。,示例值及对应分析:结构上:应与 orderCouponLedgers.discountAmount 的合计存在关系,但当前导出未填充。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryAddress IS '对应JSON字段:deliveryAddress,说明::配送地址(若存在外送业务时使用)。,示例值及对应分析:对于球房场景,当前时间范围内未使用。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.deliveryFee IS '对应JSON字段:deliveryFee,说明::配送费金额(如果支持外送业务)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ledgerAmount IS '对应JSON字段:ledgerAmount,说明::按台账口径对应的金额,一般与 discountAmount 一致或有固定关系。,示例值及对应分析:rewardPromotionMoney';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberDeductAmount IS '对应JSON字段:memberDeductAmount,说明:(结构上):会员抵扣的某种数量或金额(例如积分抵现金额、次卡次数抵扣等),当前数据未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberOfferAmount IS '对应JSON字段:memberOfferAmount,说明::由“会员权益/折扣”产生的优惠金额总计(整单维度)。,示例值及对应分析:与 memberProfile 以及台费/商品明细中的 memberDiscountAmount 有对应关系。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.onlineReturnAmount IS '对应JSON字段:onlineReturnAmount,说明::本单通过线上支付渠道退回的金额(如微信/支付宝退款)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderRemark IS '对应JSON字段:orderRemark,说明::订单备注,由收银员录入,用于记录与本单相关的特殊说明。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderSettleNumber IS '对应JSON字段:orderSettleNumber,说明:(推测):结算单编号(与 ID 独立的一套编号体系,如流水号)。当前导出时间段内未启用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payMemberBalance IS '对应JSON字段:payMemberBalance,说明:(结构上):使用会员余额支付的金额,用于区分与 balanceAmount 的不同维度(如“本次支付使用余额部分”与“余额本身变化”等),当前未实际使用。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payTime IS '对应JSON字段:payTime,说明::本单最终支付成功时间。,示例值及对应分析:和 结账记录.json 中的 payTime 对应,一般与 支付记录.create_time/pay_time 在同一时间段。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.paymentMethod IS '对应JSON字段:paymentMethod,说明::结算主支付方式编码(汇总视角)。,示例值及对应分析:对应 结账记录.json 中的 paymentMethod 字段;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountCost IS '对应JSON字段:pointDiscountCost,说明::积分抵扣对应的成本金额(成本侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.pointDiscountPrice IS '对应JSON字段:pointDiscountPrice,说明::积分抵扣对应的金额(售价侧)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.prepayMoney IS '对应JSON字段:prepayMoney,说明::预付金/定金在本单中使用的金额。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.refundAmount IS '对应JSON字段:refundAmount,说明::本单涉及的退款金额(汇总)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.returnGoodsAmount IS '对应JSON字段:returnGoodsAmount,说明::本单涉及的退货金额汇总。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.rewardName IS '对应JSON字段:rewardName,说明:(结构上):用于标识本单适用的激励方案名称,可能用于内部绩效或活动名称展示。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.settleType IS '对应JSON字段:settleType,说明::结算类型字符串标识。,示例值及对应分析:"SiteOrder":店内消费订单结算。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteAddress IS '对应JSON字段:siteAddress,说明::门店地址(详细地址)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteBusinessTel IS '对应JSON字段:siteBusinessTel,说明::门店电话。,示例值及对应分析:用途:用于小票打印上的客服电话。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteId IS '对应JSON字段:siteId,说明::门店 ID。,示例值及对应分析:关联:';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.siteName IS '对应JSON字段:siteName,说明::门店名称,如“朗朗桌球”。,示例值及对应分析:用途:小票上展示门店名。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantId IS '对应JSON字段:tenantId,说明::租户 / 商户 ID(品牌维度)。,示例值及对应分析:当前数据:恒定为同一值,表示所有记录都来自同一商户。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantName IS '对应JSON字段:tenantName,说明::租户名称,如“朗朗桌球”。,示例值及对应分析:当前数据:全表统一一个值。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketCustomContent IS '对应JSON字段:ticketCustomContent,说明::自定义小票内容,如商家自定义宣传语、条款等。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.ticketRemark IS '对应JSON字段:ticketRemark,说明::小票备注内容,可用于打印在小票底部或顶部(例如活动说明、特别提示)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.voucherMoney IS '对应JSON字段:voucherMoney,说明::代金券类金额字段(可能用于某类“代金券余额”或“券面值”记录)。,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.memberProfile IS '对应JSON字段:memberProfile,说明::,示例值及对应分析:不是会员卡主键,而是本次结账时的会员信息快照;';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.orderItem IS '对应JSON字段:orderItem,说明::本次结算对应的“订单明细列表”,这部分是连接“台费流水 / 商品出库 / 券使用”等多个子领域的关键结构。,示例值及对应分析:下面专门展开 orderItem 及其子结构。';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.tenantMemberCardLogs IS '对应JSON字段:tenantMemberCardLogs,说明:?????? settlement_ticket_details-Analysis.md,示例值及对应分析:?? settlement_ticket_details-Analysis.md';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.settlement_ticket_details.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_master (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteName TEXT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_bar_code TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ oneCategoryName TEXT,
+ twoCategoryName TEXT,
+ unit TEXT,
+ sale_price NUMERIC(18,4),
+ cost_price NUMERIC(18,4),
+ cost_price_type INT,
+ min_discount_price NUMERIC(18,4),
+ safe_stock NUMERIC(18,4),
+ stock NUMERIC(18,4),
+ stock_A NUMERIC(18,4),
+ sale_num NUMERIC(18,4),
+ total_purchase_cost NUMERIC(18,4),
+ total_sales NUMERIC(18,4),
+ average_monthly_sales NUMERIC(18,4),
+ batch_stock_quantity NUMERIC(18,2),
+ days_available INT,
+ provisional_total_cost NUMERIC(18,2),
+ enable_status INT,
+ audit_status INT,
+ goods_state INT,
+ is_delete INT,
+ is_warehousing INT,
+ able_discount INT,
+ able_site_transfer INT,
+ forbid_sell_status INT,
+ "freeze" INT,
+ send_state INT,
+ custom_label_type INT,
+ option_required INT,
+ sale_channel INT,
+ sort INT,
+ remark TEXT,
+ pinyin_initial TEXT,
+ goods_cover TEXT,
+ create_time TIMESTAMP,
+ update_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_master IS '对应JSON字段:store_goods_master.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.id IS '对应JSON字段:id,说明::门店商品 ID,门店维度的商品主键。,示例值及对应分析:用途:在其它文件中经常以 site_goods_id 的名字出现,与这里的 id 一致,用来关联库存记录、销售记录等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。同一品牌下多个门店共享一个 tenant_id。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一品牌)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.site_id IS '对应JSON字段:site_id,说明::门店 ID。,示例值及对应分析:枚举情况:本文件中为单一固定值(同一家门店“朗朗桌球”),和其它 JSON 中的 site_id 一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.siteName IS '对应JSON字段:siteName,说明::门店名称,是对 site_id 的冗余展示,方便直接阅读,无需再去关联门店档案。,示例值及对应分析:2. 商品标识和分类维度';
+COMMENT ON COLUMN billiards_ods.store_goods_master.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户/品牌维度的商品 ID,相当于“全局商品 ID”。,示例值及对应分析:用途:用于跨门店或与“商品档案(商品档案.json)”对齐时使用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_name IS '对应JSON字段:goods_name,说明::商品名称,例如“合味道泡面”“地道肠”“麻将房茶位费”等。,示例值及对应分析:用途:业务展示字段,历史流水里也会冗余存一份商品名。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_bar_code IS '对应JSON字段:goods_bar_code,说明::商品条形码(如 EAN-13 编码),用于扫码销售。此字段设计为可填,但此店目前未配置。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_category_id IS '对应JSON字段:goods_category_id,说明::商品一级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_second_category_id IS '对应JSON字段:goods_second_category_id,说明::商品二级分类 ID。,示例值及对应分析:用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.oneCategoryName IS '对应JSON字段:oneCategoryName,说明::一级分类名称,如“零食”“酒水”“服务费”等。,示例值及对应分析:说明:与 goods_category_id 一一对应,是易读文本字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.twoCategoryName IS '对应JSON字段:twoCategoryName,说明::二级分类名称,如“面”“洋酒”“纸巾”等。,示例值及对应分析:说明:与 goods_second_category_id 对应。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.unit IS '对应JSON字段:unit,说明::商品计量单位(销售单位)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_price IS '对应JSON字段:sale_price,说明::商品标准销售价(挂牌价),单位为元。,示例值及对应分析:说明:实际结算时可能会打折或用券抵扣,但这个字段表示“定价”。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price IS '对应JSON字段:cost_price,说明::商品成本价(单件成本)。,示例值及对应分析:观察:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.cost_price_type IS '对应JSON字段:cost_price_type,说明:(结合成本字段推测):,示例值及对应分析:1 代表使用“固定成本价”(手工维护的 cost_price),provisional_total_cost 按“数量 × cost_price”算。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.min_discount_price IS '对应JSON字段:min_discount_price,说明::最低允许成交价(限价)。,示例值及对应分析:用法逻辑(推测):';
+COMMENT ON COLUMN billiards_ods.store_goods_master.safe_stock IS '对应JSON字段:safe_stock,说明::安全库存量(阈值),低于该值时系统可以提示补货。,示例值及对应分析:当前门店尚未设置安全库存,所以全部为 0,仅起到结构占位作用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock IS '对应JSON字段:stock,说明::当前可用库存数量(以 unit 为单位)。,示例值及对应分析:特征:可以是 0(库存卖完),也可以非常大(例如纸巾、茶位费这种按“份”计的虚拟库存设定)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.stock_A IS '对应JSON字段:stock_A,说明:(系统设计):副单位库存数量。如果商品存在双单位(例如箱/瓶),stock_A 通常用于记录副单位库存。当前门店没有启用副单位库存管理,因此为 0。,示例值及对应分析:batch_stock_quantity';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_num IS '对应JSON字段:sale_num,说明::在当前统计口径下的销售数量(总销量,单位同 unit)。,示例值及对应分析:特征:和 total_sales 完全一致(当前导出时的统计口径下),说明两者是同一统计周期。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_purchase_cost IS '对应JSON字段:total_purchase_cost,说明::总采购成本,单位为元。,示例值及对应分析:当前数据:与 provisional_total_cost 完全相等。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.total_sales IS '对应JSON字段:total_sales,说明:(从命名看):累计销售数量。,示例值及对应分析:实际:当前数据中 total_sales == sale_num,说明此接口的统计区间 = “截至当前的全部历史”,因此数量一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.average_monthly_sales IS '对应JSON字段:average_monthly_sales,说明::平均月销量(件/月),根据某个统计周期内的销售数据折算而来。,示例值及对应分析:结构特征:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.enable_status IS '对应JSON字段:enable_status,说明:(结合名称与常见编码):,示例值及对应分析:1:启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.audit_status IS '对应JSON字段:audit_status,说明:(典型业务语义):,示例值及对应分析:2:审核通过。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_state IS '对应JSON字段:goods_state,说明:类型:int,枚举,示例值及对应分析:观察值:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:未删除(有效档案);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.is_warehousing IS '对应JSON字段:is_warehousing,说明::是否纳入库存管理。,示例值及对应分析:1:启用库存管理(会有出入库流水)。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_discount IS '对应JSON字段:able_discount,说明:(结合命名):,示例值及对应分析:是否允许参与折扣。当前全部为 1,说明所有商品都允许打折。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.able_site_transfer IS '对应JSON字段:able_site_transfer,说明:(结合命名与值分布):,示例值及对应分析:表示是否允许跨门店调拨或跨站点共享库存。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.forbid_sell_status IS '对应JSON字段:forbid_sell_status,说明:类型:int,枚举,示例值及对应分析:观察值:全部为 1。';
+COMMENT ON COLUMN billiards_ods.store_goods_master."freeze" IS '对应JSON字段:freeze,说明::冻结状态。,示例值及对应分析:0:未冻结;';
+COMMENT ON COLUMN billiards_ods.store_goods_master.send_state IS '对应JSON字段:send_state,说明:(命名趋近“上架状态/可售状态”):,示例值及对应分析:1:可销售/可下单。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.custom_label_type IS '对应JSON字段:custom_label_type,说明:(推测):自定义标签类型。,示例值及对应分析:1:使用系统默认标签(未出现);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.option_required IS '对应JSON字段:option_required,说明:(推测):是否需要在销售时选择规格/选项。,示例值及对应分析:1:不要求额外选项(单规格商品);';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sale_channel IS '对应JSON字段:sale_channel,说明::销售渠道类型。,示例值及对应分析:常见模式:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.sort IS '对应JSON字段:sort,说明::前端展示或内部配置的排序号,数值越小/越大排前取决于业务约定。';
+COMMENT ON COLUMN billiards_ods.store_goods_master.remark IS '对应JSON字段:remark,说明::商品备注(可以写口味说明、供应商、注意事项等)。当前尚未使用。,示例值及对应分析:sort';
+COMMENT ON COLUMN billiards_ods.store_goods_master.pinyin_initial IS '对应JSON字段:pinyin_initial,说明::商品名称的拼音首字母缩写,有时多个别名用逗号分隔。,示例值及对应分析:作用:';
+COMMENT ON COLUMN billiards_ods.store_goods_master.goods_cover IS '对应JSON字段:goods_cover,说明::商品图片 URL(如 OSS 对象存储地址),用于前端展示商品图片。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.create_time IS '对应JSON字段:create_time,说明::门店商品档案创建时间(商品在门店建立档案的时间点)。,示例值及对应分析:?? store_goods_master-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_master.update_time IS '对应JSON字段:update_time,说明::最后一次修改该商品档案的时间(包括价格调整、状态变更等)。,示例值及对应分析:days_available';
+COMMENT ON COLUMN billiards_ods.store_goods_master.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_master.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
+
+CREATE TABLE IF NOT EXISTS billiards_ods.store_goods_sales_records (
+ id BIGINT PRIMARY KEY,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ siteid BIGINT,
+ sitename TEXT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ order_settle_id BIGINT,
+ order_trade_no TEXT,
+ order_goods_id BIGINT,
+ ordergoodsid BIGINT,
+ order_pay_id BIGINT,
+ order_coupon_id BIGINT,
+ ledger_name TEXT,
+ ledger_group_name TEXT,
+ ledger_amount NUMERIC(18,2),
+ ledger_count NUMERIC(18,4),
+ ledger_unit_price NUMERIC(18,4),
+ ledger_status INT,
+ discount_money NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ sales_type INT,
+ is_single_order INT,
+ is_delete INT,
+ goods_remark TEXT,
+ option_price NUMERIC(18,2),
+ option_value_name TEXT,
+ option_name TEXT,
+ member_coupon_id BIGINT,
+ package_coupon_id BIGINT,
+ sales_man_org_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_user_id BIGINT,
+ operator_id BIGINT,
+ operator_name TEXT,
+ openSalesman TEXT,
+ returns_number INT,
+ site_table_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ create_time TIMESTAMP,
+ payload JSONB NOT NULL,
+ source_file TEXT,
+ source_endpoint TEXT,
+ fetched_at TIMESTAMPTZ DEFAULT now()
+);
+
+COMMENT ON TABLE billiards_ods.store_goods_sales_records IS '对应JSON字段:store_goods_sales_records.json,说明:ODS 原始明细表(保留payload),示例值及对应分析:详见 store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.id IS '对应JSON字段:id,说明::本条「门店销售流水」记录的主键 ID。,示例值及对应分析:用途:在系统内部唯一标识这一条销售明细。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_id IS '对应JSON字段:tenant_id,说明::租户/品牌 ID。,示例值及对应分析:特征:所有记录为同一个值,对应「非球科技系统中你的商户」。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_id IS '对应JSON字段:site_id,说明::门店 ID(系统主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_goods_id IS '对应JSON字段:site_goods_id,说明::门店商品 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_id IS '对应JSON字段:tenant_goods_id,说明::租户(品牌)级商品 ID(全局商品 ID)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_settle_id IS '对应JSON字段:order_settle_id,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_trade_no IS '对应JSON字段:order_trade_no,说明:与台费、助教、团购套餐流水等表共享,形成「订单主表(结算)– 多种明细表」的结构。,示例值及对应分析:如果结账记录表有数据,order_settle_id 对应那里的主键,create_time 与订单结束时间基本一致。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_goods_id IS '对应JSON字段:order_goods_id,说明::订单商品明细 ID(订单内部的商品行主键)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_pay_id IS '对应JSON字段:order_pay_id,说明:连接到「支付记录」中的一条支付流水,再通过支付的 relate_type/relate_id 把支付和订单、充值等业务区分开。,示例值及对应分析:对于退款,则通过退款记录里的 relate_type/relate_id 反向关联到原来的订单或支付。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.order_coupon_id IS '对应JSON字段:order_coupon_id,说明::订单级优惠券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_name IS '对应JSON字段:ledger_name,说明::销售项目名称(商品名称),例如 “哇哈哈矿泉水”“地道肠”“东方树叶”等。,示例值及对应分析:说明:业务展示用字段,历史流水即使商品改名,这里会保留当时的名字。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_group_name IS '对应JSON字段:ledger_group_name,说明::销售项目所属的「门店内部分组名称」,类似前台菜单分组或大类标签。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_amount IS '对应JSON字段:ledger_amount,说明::原始应收金额,公式上接近 ledger_unit_price × ledger_count。,示例值及对应分析:说明:这是未考虑优惠前的金额基础,用于后续计算折扣和抵扣。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_count IS '对应JSON字段:ledger_count,说明::销售数量(以 unit 为单位,unit 字段在门店商品档案中)。,示例值及对应分析:观测值:如 1, 2, 3, 6, 36 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_unit_price IS '对应JSON字段:ledger_unit_price,说明::商品在该次销售中的「结算单价」(元/单位)。,示例值及对应分析:观测值示例:5.0, 8.0, 2.0, 10.0, 72.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.ledger_status IS '对应JSON字段:ledger_status,说明::销售流水状态。,示例值及对应分析:1:正常有效。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.discount_money IS '对应JSON字段:discount_money,说明::本条销售明细的「价格优惠金额」,即原价部分被减免掉的金额。,示例值及对应分析:典型关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.coupon_deduct_money IS '对应JSON字段:coupon_deduct_money,说明::被优惠券 / 团购券直接抵扣到这条商品明细上的金额。,示例值及对应分析:说明:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_discount_amount IS '对应JSON字段:member_discount_amount,说明::由会员身份(会员折扣)针对这一行商品产生的优惠金额。,示例值及对应分析:说明:尽管字段存在,但当前实际折扣可能合并反映在 discount_money 中,这个字段没有拆开体现。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_coupon_deduct_money IS '对应JSON字段:option_coupon_deduct_money,说明::由优惠券抵扣“选项价格”的金额。,示例值及对应分析:上面这三个 option_* 字段,是为“主商品 + 选项”的更复杂计价方式预留的,本店当前所有记录都是单规格,选项体系未启用。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_member_discount_money IS '对应JSON字段:option_member_discount_money,说明::由会员折扣作用在“选项价格”上的优惠金额。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money IS '对应JSON字段:point_discount_money,说明::由积分抵扣的金额(顾客兑换积分抵现金额)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.point_discount_money_cost IS '对应JSON字段:point_discount_money_cost,说明::积分抵扣对应的“成本金额”(后台核算用),例如按积分成本来计提费用。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.real_goods_money IS '对应JSON字段:real_goods_money,说明::商品实际入账金额(考虑折扣、可能还会考虑其它抵扣后的实际销售金额)。,示例值及对应分析:观测值:5.0, 10.0, 8.0, 6.0, 4.0 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.cost_money IS '对应JSON字段:cost_money,说明::本条销售对应的成本金额(以元计)。,示例值及对应分析:观测示例:0.01, 0.00, 3.58, 1.79, 0.64 等。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.push_money IS '对应JSON字段:push_money,说明::本条销售对应的提成金额(给营业员/促销员的提成)。,示例值及对应分析:在启用营业员体系时,这里才会出现正数。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_type IS '对应JSON字段:sales_type,说明::销售类型。,示例值及对应分析:1:正常销售;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_single_order IS '对应JSON字段:is_single_order,说明::是否单独订单标识。,示例值及对应分析:1:作为独立明细参与某个订单结算;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.is_delete IS '对应JSON字段:is_delete,说明::逻辑删除标志。,示例值及对应分析:0:正常有效;';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.goods_remark IS '对应JSON字段:goods_remark,说明::商品备注/口味说明/特殊说明。,示例值及对应分析:用途:点单时如果需要额外说明,可以写在这里。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_price IS '对应JSON字段:option_price,说明::商品选项(规格/加料)的附加价格。,示例值及对应分析:说明:如加冰、加料、升级大杯等产生附加费用时,理论上应该体现到这里。当前门店未使用此功能。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_value_name IS '对应JSON字段:option_value_name,说明::商品选项名称(如规格、口味:大杯/小杯,不加冰等)。,示例值及对应分析:结构用途:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.option_name IS '对应JSON字段:option_name,说明:?????? store_goods_sales_records-Analysis.md,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.member_coupon_id IS '对应JSON字段:member_coupon_id,说明::会员券 ID(比如会员专享优惠券)。,示例值及对应分析:当前数据未使用,属于为会员权益预留的字段。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.package_coupon_id IS '对应JSON字段:package_coupon_id,说明::套餐券 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.sales_man_org_id IS '对应JSON字段:sales_man_org_id,说明::营业员所属组织/部门 ID。,示例值及对应分析:当前门店全部为 0,说明未启用这套销售员分组织的体系。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_name IS '对应JSON字段:salesman_name,说明::营业员姓名(如果有为具体销售员记业绩,则在此填姓名)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_role_id IS '对应JSON字段:salesman_role_id,说明::营业员的系统角色 ID(例如某个角色代码表示“销售员”)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.salesman_user_id IS '对应JSON字段:salesman_user_id,说明::营业员用户 ID(系统账号 ID)。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_id IS '对应JSON字段:operator_id,说明::操作员 ID(录入这笔销售的员工)。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.operator_name IS '对应JSON字段:operator_name,说明::操作员姓名,文字冗余。,示例值及对应分析:?? store_goods_sales_records-Analysis.md';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.openSalesman IS '对应JSON字段:openSalesman,说明:(结合系统其它文件推断):,示例值及对应分析:1:启用“营业员/销售员”机制(要指定 salesman);';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.site_table_id IS '对应JSON字段:site_table_id,说明::球台 ID。,示例值及对应分析:非 0:销售记录关联到具体某张桌台(例如顾客在台上点饮料)。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_business_id IS '对应JSON字段:tenant_goods_business_id,说明::租户级商品「业务大类」ID(例如“零食类”“酒水类”等更高维度)。,示例值及对应分析:2.2 门店 / 球台维度字段';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.tenant_goods_category_id IS '对应JSON字段:tenant_goods_category_id,说明::租户级商品一级分类 ID。,示例值及对应分析:关系:';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.create_time IS '对应JSON字段:create_time,说明::销售记录创建时间,通常就是结账时间或录入时间。,示例值及对应分析:用途:用于按时间维度查询销售流水,与订单层的时间字段对齐。';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.payload IS '对应JSON字段:payload,说明:完整原始 JSON 内容,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_file IS '对应JSON字段:source_file,说明:原始文件名(含时间戳后缀),示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.source_endpoint IS '对应JSON字段:source_endpoint,说明:抓取来源接口/URL 标识,示例值及对应分析:???????';
+COMMENT ON COLUMN billiards_ods.store_goods_sales_records.fetched_at IS '对应JSON字段:fetched_at,说明:入库时间(ETL 拉取时间),示例值及对应分析:???????';
diff --git a/tmp/schema_dwd.sql b/tmp/schema_dwd.sql
new file mode 100644
index 0000000..90f3849
--- /dev/null
+++ b/tmp/schema_dwd.sql
@@ -0,0 +1,1801 @@
+-- Billiards DWD schema for LLZQ-test (schema: billiards_dwd)
+-- Source: DWD layer design draft (DWD_ceng_sheji_caogao.md); merged schema definitions and SCD2 columns (replaces schema_dwd_doc.sql + schema_dwd_scd2.sql)
+
+-- Generated from DWD?????.docx; includes column comments from??
+CREATE SCHEMA IF NOT EXISTS billiards_dwd;
+SET search_path TO billiards_dwd;
+
+-- dim_site
+CREATE TABLE IF NOT EXISTS dim_site (
+ site_id BIGINT,
+ org_id BIGINT,
+ shop_name TEXT,
+ business_tel TEXT,
+ full_address TEXT,
+ tenant_id BIGINT,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
+COMMENT ON COLUMN dim_site.org_id IS '上级组织 ID,用于区域组织划分。 | 来源: siteProfile.org_id | 角色: 外键';
+COMMENT ON COLUMN dim_site.shop_name IS '门店名称,展示用。 | 来源: siteProfile.shop_name';
+COMMENT ON COLUMN dim_site.business_tel IS '门店电话。 | 来源: siteProfile.business_tel';
+COMMENT ON COLUMN dim_site.full_address IS '门店完整地址。 | 来源: siteProfile.full_address';
+COMMENT ON COLUMN dim_site.tenant_id IS '租户 ID。与其它表 tenant_id 对应。 | 来源: siteProfile.tenant_id | 角色: 外键';
+
+-- dim_site_Ex
+CREATE TABLE IF NOT EXISTS dim_site_Ex (
+ site_id BIGINT,
+ avatar TEXT,
+ address TEXT,
+ longitude NUMERIC(9,6),
+ latitude NUMERIC(9,6),
+ tenant_site_region_id BIGINT,
+ auto_light INTEGER,
+ light_status INTEGER,
+ light_type INTEGER,
+ light_token TEXT,
+ site_type INTEGER,
+ site_label TEXT,
+ attendance_enabled INTEGER,
+ attendance_distance INTEGER,
+ customer_service_qrcode TEXT,
+ customer_service_wechat TEXT,
+ fixed_pay_qrCode TEXT,
+ prod_env TEXT,
+ shop_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site_Ex.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
+COMMENT ON COLUMN dim_site_Ex.avatar IS '门店头像 URL。 | 来源: siteProfile.avatar';
+COMMENT ON COLUMN dim_site_Ex.address IS '地址简写。 | 来源: siteProfile.address';
+COMMENT ON COLUMN dim_site_Ex.longitude IS '经度。 | 来源: siteProfile.longitude';
+COMMENT ON COLUMN dim_site_Ex.latitude IS '纬度。 | 来源: siteProfile.latitude';
+COMMENT ON COLUMN dim_site_Ex.tenant_site_region_id IS '地区编码。 | 来源: siteProfile.tenant_site_region_id';
+COMMENT ON COLUMN dim_site_Ex.auto_light IS '是否自动控制灯光:1=是,2=否(根据系统约定)。 | 来源: siteProfile.auto_light';
+COMMENT ON COLUMN dim_site_Ex.light_status IS '灯光状态,系统预留字段。 | 来源: siteProfile.light_status';
+COMMENT ON COLUMN dim_site_Ex.light_type IS '灯光类型,预留字段。 | 来源: siteProfile.light_type';
+COMMENT ON COLUMN dim_site_Ex.light_token IS '灯光控制令牌。 | 来源: siteProfile.light_token';
+COMMENT ON COLUMN dim_site_Ex.site_type IS '门店类型枚举(未在导出中说明,视系统配置)。 | 来源: siteProfile.site_type';
+COMMENT ON COLUMN dim_site_Ex.site_label IS '门店标签,展示用。 | 来源: siteProfile.site_label';
+COMMENT ON COLUMN dim_site_Ex.attendance_enabled IS '门店是否启用考勤功能:1=启用,2=不启用。 | 来源: siteProfile.attendance_enabled';
+COMMENT ON COLUMN dim_site_Ex.attendance_distance IS '考勤打卡距离限制(米)。 | 来源: siteProfile.attendance_distance';
+COMMENT ON COLUMN dim_site_Ex.customer_service_qrcode IS '客服二维码 URL。 | 来源: siteProfile.customer_service_qrcode';
+COMMENT ON COLUMN dim_site_Ex.customer_service_wechat IS '客服微信号。 | 来源: siteProfile.customer_service_wechat';
+COMMENT ON COLUMN dim_site_Ex.fixed_pay_qrCode IS '固定收款二维码。 | 来源: siteProfile.fixed_pay_qrCode';
+COMMENT ON COLUMN dim_site_Ex.prod_env IS '环境标记(生产/测试)。 | 来源: siteProfile.prod_env';
+COMMENT ON COLUMN dim_site_Ex.shop_status IS '门店状态,未在文档解释。 | 来源: siteProfile.shop_status';
+COMMENT ON COLUMN dim_site_Ex.create_time IS '门店创建时间。 | 来源: siteProfile.create_time';
+COMMENT ON COLUMN dim_site_Ex.update_time IS '门店最近更新时间。 | 来源: siteProfile.update_time';
+
+-- dim_table
+CREATE TABLE IF NOT EXISTS dim_table (
+ table_id BIGINT,
+ site_id BIGINT,
+ table_name TEXT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ table_price NUMERIC(18,2),
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table.site_id IS '门店 ID。 | 来源: siteId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_name IS '台桌名称/编号,如 A17、888。 | 来源: tableName';
+COMMENT ON COLUMN dim_table.site_table_area_id IS '门店区 ID,用于区分 A区/B区/补时区等。 | 来源: siteTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.site_table_area_name IS '区域名称,如 “A区”“补时长”。 | 来源: siteTableAreaName';
+COMMENT ON COLUMN dim_table.tenant_table_area_id IS '租户级区域 ID。 | 来源: tenantTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_price IS '台桌基础单价,从table_fee_transactions取值。方法:对应本表id,table_fee_transactions表的site_table_id。';
+
+-- cleanup legacy column
+ALTER TABLE IF EXISTS billiards_dwd.dim_table
+ DROP COLUMN IF EXISTS tenant_id;
+
+-- dim_table_Ex
+CREATE TABLE IF NOT EXISTS dim_table_Ex (
+ table_id BIGINT,
+ show_status INTEGER,
+ is_online_reservation INTEGER,
+ table_cloth_use_time INTEGER,
+ table_cloth_use_cycle INTEGER,
+ table_status INTEGER,
+ last_maintenance_time TIMESTAMPTZ,
+ remark TEXT,
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table_Ex.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table_Ex.show_status IS '显示状态:1=正常台;其他值=特殊用途(包厢、补时长等)。 | 来源: showStatus';
+COMMENT ON COLUMN dim_table_Ex.is_online_reservation IS '是否可线上预约:1=是,2=否。 | 来源: isOnlineReservation';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_time IS '已使用台呢时长(秒)。 | 来源: tableClothUseTime';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_cycle IS '台呢更换周期阈值(秒)。 | 来源: tableClothUseCycle';
+COMMENT ON COLUMN dim_table_Ex.table_status IS '当前台桌状态:1=空闲,2=使用中,3=暂停中,4=锁定。 | 来源: tableStatus';
+COMMENT ON COLUMN dim_table_Ex.last_maintenance_time IS '最近保养时间(未在 JSON 中出现)。 | 来源: lastMaintenanceTime';
+COMMENT ON COLUMN dim_table_Ex.remark IS '备注信息。 | 来源: remark';
+
+-- dim_assistant
+CREATE TABLE IF NOT EXISTS dim_assistant (
+ assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_no TEXT,
+ real_name TEXT,
+ nickname TEXT,
+ mobile TEXT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ team_id BIGINT,
+ team_name TEXT,
+ level INTEGER,
+ entry_time TIMESTAMPTZ,
+ resign_time TIMESTAMPTZ,
+ leave_status INTEGER,
+ assistant_status INTEGER,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant.user_id IS '系统用户 ID,用于统一跨模块身份。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.assistant_no IS '助教工号/编号,业务识别用。 | 来源: assistant_no';
+COMMENT ON COLUMN dim_assistant.real_name IS '助教真实姓名。 | 来源: real_name';
+COMMENT ON COLUMN dim_assistant.nickname IS '前台展示昵称。 | 来源: nickname';
+COMMENT ON COLUMN dim_assistant.mobile IS '手机号码。 | 来源: mobile';
+COMMENT ON COLUMN dim_assistant.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.site_id IS '门店 ID。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_id IS '助教团队 ID。 | 来源: team_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_name IS '团队名称。 | 来源: team_name';
+COMMENT ON COLUMN dim_assistant.level IS '助教等级:8=管理员、10=初级、20=中级、30=高级、40=专家。 | 来源: level';
+COMMENT ON COLUMN dim_assistant.entry_time IS '入职时间。 | 来源: entry_time';
+COMMENT ON COLUMN dim_assistant.resign_time IS '离职时间;远未来日期表示在职。 | 来源: resign_time';
+COMMENT ON COLUMN dim_assistant.leave_status IS '在职状态:0=在职,1=已离职。 | 来源: leave_status';
+COMMENT ON COLUMN dim_assistant.assistant_status IS '账号启用状态:1=启用,2=停用/冻结。 | 来源: assistant_status';
+
+-- dim_assistant_Ex
+CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
+ assistant_id BIGINT,
+ gender INTEGER,
+ birth_date TIMESTAMPTZ,
+ avatar TEXT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ height NUMERIC(5,2),
+ weight NUMERIC(5,2),
+ shop_name TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ person_org_id BIGINT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ assistant_grade DOUBLE PRECISION,
+ sum_grade DOUBLE PRECISION,
+ get_grade_times INTEGER,
+ charge_way INTEGER,
+ allow_cx INTEGER,
+ is_guaranteed INTEGER,
+ salary_grant_enabled INTEGER,
+ entry_type INTEGER,
+ entry_sign_status INTEGER,
+ resign_sign_status INTEGER,
+ work_status INTEGER,
+ show_status INTEGER,
+ show_sort INTEGER,
+ online_status INTEGER,
+ is_delete INTEGER,
+ criticism_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ last_update_name TEXT,
+ order_trade_no BIGINT,
+ ding_talk_synced INTEGER,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ light_status INTEGER,
+ is_team_leader INTEGER,
+ serial_number BIGINT,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant_Ex.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant_Ex.gender IS '性别枚举:0=未填/保密,1=男,2=女。 | 来源: gender';
+COMMENT ON COLUMN dim_assistant_Ex.birth_date IS '出生日期,默认为 0001-01-01 表示未设置。 | 来源: birth_date';
+COMMENT ON COLUMN dim_assistant_Ex.avatar IS '头像 URL。 | 来源: avatar';
+COMMENT ON COLUMN dim_assistant_Ex.introduce IS '个人简介文案(目前为空)。 | 来源: introduce';
+COMMENT ON COLUMN dim_assistant_Ex.video_introduction_url IS '视频介绍 URL。 | 来源: video_introduction_url';
+COMMENT ON COLUMN dim_assistant_Ex.height IS '身高(厘米),0 表示未填。 | 来源: height';
+COMMENT ON COLUMN dim_assistant_Ex.weight IS '体重(公斤),0 表示未填。 | 来源: weight';
+COMMENT ON COLUMN dim_assistant_Ex.shop_name IS '门店名称。 | 来源: shop_name';
+COMMENT ON COLUMN dim_assistant_Ex.group_id IS '上级分组 ID,未使用。 | 来源: group_id';
+COMMENT ON COLUMN dim_assistant_Ex.group_name IS '上级分组名称,空。 | 来源: group_name';
+COMMENT ON COLUMN dim_assistant_Ex.person_org_id IS '人事组织 ID,用于权限和报表分组。 | 来源: person_org_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_id IS '预留员工 ID(全部为0)。 | 来源: staff_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_profile_id IS '外部人事档案 ID(全部为0)。 | 来源: staff_profile_id';
+COMMENT ON COLUMN dim_assistant_Ex.assistant_grade IS '平均评分(0 表示暂无)。 | 来源: assistant_grade';
+COMMENT ON COLUMN dim_assistant_Ex.sum_grade IS '总评分累加值。 | 来源: sum_grade';
+COMMENT ON COLUMN dim_assistant_Ex.get_grade_times IS '累计评分次数。 | 来源: get_grade_times';
+COMMENT ON COLUMN dim_assistant_Ex.charge_way IS '计费方式:2=计时,其他未出现。 | 来源: charge_way';
+COMMENT ON COLUMN dim_assistant_Ex.allow_cx IS '是否允许促销计费:1=允许。 | 来源: allow_cx';
+COMMENT ON COLUMN dim_assistant_Ex.is_guaranteed IS '是否有保底:1=是。 | 来源: is_guaranteed';
+COMMENT ON COLUMN dim_assistant_Ex.salary_grant_enabled IS '薪资发放开关(值2,具体含义未知)。 | 来源: salary_grant_enabled';
+COMMENT ON COLUMN dim_assistant_Ex.entry_type IS '入职类型:1=正式;其他未出现。 | 来源: entry_type';
+COMMENT ON COLUMN dim_assistant_Ex.entry_sign_status IS '入职签约状态:0=未签约,1=已签约(未出现)。 | 来源: entry_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.resign_sign_status IS '离职签约状态,未出现非 0。 | 来源: resign_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.work_status IS '工作状态:1=在岗,2=离岗。与 leave_status 呼应。 | 来源: work_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_status IS '前台展示状态:1=显示;其他值未出现。 | 来源: show_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_sort IS '前端排序序号。 | 来源: show_sort';
+COMMENT ON COLUMN dim_assistant_Ex.online_status IS '在线状态:1=在线。 | 来源: online_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_delete IS '逻辑删除标记:0=未删除,1=已删除。 | 来源: is_delete';
+COMMENT ON COLUMN dim_assistant_Ex.criticism_status IS '投诉状态:1=正常,2=有投诉。 | 来源: criticism_status';
+COMMENT ON COLUMN dim_assistant_Ex.create_time IS '账号创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_assistant_Ex.update_time IS '账号最近修改时间。 | 来源: update_time';
+COMMENT ON COLUMN dim_assistant_Ex.start_time IS '配置生效开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_assistant_Ex.end_time IS '配置生效结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_id IS '最近服务的台桌 ID(未必存在)。 | 来源: last_table_id';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_name IS '最近服务球台名称。 | 来源: last_table_name';
+COMMENT ON COLUMN dim_assistant_Ex.last_update_name IS '最近更新该账号的管理员。 | 来源: last_update_name';
+COMMENT ON COLUMN dim_assistant_Ex.order_trade_no IS '最近关联的订单号(非外键,仅做展示)。 | 来源: order_trade_no';
+COMMENT ON COLUMN dim_assistant_Ex.ding_talk_synced IS '是否同步钉钉:1=已同步。 | 来源: ding_talk_synced';
+COMMENT ON COLUMN dim_assistant_Ex.site_light_cfg_id IS '灯控配置 ID(未启用)。 | 来源: site_light_cfg_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_equipment_id IS '灯控设备 ID(未启用)。 | 来源: light_equipment_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_status IS '灯控状态(值2,具体含义未知)。 | 来源: light_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_team_leader IS '是否团队长:0=否,1=是。 | 来源: is_team_leader';
+COMMENT ON COLUMN dim_assistant_Ex.serial_number IS '来源: serial_number';
+
+-- dim_member
+CREATE TABLE IF NOT EXISTS dim_member (
+ member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ mobile TEXT,
+ nickname TEXT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member.system_member_id IS '跨租户全局会员 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.register_site_id IS '注册门店 ID。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.mobile IS '会员手机号。 | 来源: mobile';
+COMMENT ON COLUMN dim_member.nickname IS '昵称(未必是真实姓名)。 | 来源: nickname';
+COMMENT ON COLUMN dim_member.member_card_grade_code IS '会员等级代码:1=金卡?2=银卡?3=钻石卡?4=黑卡?(按照 MD 文档枚举)。 | 来源: member_card_grade_code';
+COMMENT ON COLUMN dim_member.member_card_grade_name IS '等级名称,中文描述。 | 来源: member_card_grade_name';
+COMMENT ON COLUMN dim_member.create_time IS '会员档案创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_member.update_time IS '最近更新时间。 | 来源: update_time';
+
+-- dim_member_Ex
+CREATE TABLE IF NOT EXISTS dim_member_Ex (
+ member_id BIGINT,
+ referrer_member_id BIGINT,
+ point NUMERIC(18,2),
+ register_site_name TEXT,
+ growth_value NUMERIC(18,2),
+ user_status INTEGER,
+ status INTEGER,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member_Ex.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_Ex.referrer_member_id IS '推荐人会员 ID,营销分析用。 | 来源: referrer_member_id';
+COMMENT ON COLUMN dim_member_Ex.point IS '积分余额(暂未启用)。 | 来源: point';
+COMMENT ON COLUMN dim_member_Ex.register_site_name IS '注册门店名称。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_Ex.growth_value IS '成长值,暂未启用。 | 来源: growth_value';
+COMMENT ON COLUMN dim_member_Ex.user_status IS '会员状态枚举:1=正常,其它值未出现。 | 来源: user_status';
+COMMENT ON COLUMN dim_member_Ex.status IS '帐户状态:1=正常;其它值未出现。 | 来源: status';
+
+-- dim_member_card_account
+CREATE TABLE IF NOT EXISTS dim_member_card_account (
+ member_card_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ card_type_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ balance NUMERIC(18,2),
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_consume_time TIMESTAMPTZ,
+ status INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account.tenant_id IS '租户/品牌 ID,用于分隔不同业务主体。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.register_site_id IS '开卡门店 ID,对应 dim_site.site_id。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.tenant_member_id IS '对应会员档案中的 member_id(本租户内)。0 表示未绑定会员。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.system_member_id IS '全局会员 ID,用于跨租户统一会员身份。0 表示未绑定会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.card_type_id IS '卡种 ID,指向卡种配置表。与下面的 grade_code 共同定义卡类别。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code IS '卡等级/卡类代码,区别不同类别卡。2790683528022853=储值卡,2790683528022856=活动抵用券,2790683528022855=台费卡,2790683528022858=酒水卡,2790683528022857=月卡';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code_name IS '卡等级中文名称,与 member_card_grade_code 一一对应。 | 来源: member_card_grade_code_name';
+COMMENT ON COLUMN dim_member_card_account.member_card_type_name IS '卡类型名称,通常与 grade_code_name 相同,纯展示字段。 | 来源: member_card_type_name';
+COMMENT ON COLUMN dim_member_card_account.member_name IS '持卡会员姓名快照,部分为空表示未绑定。 | 来源: member_name';
+COMMENT ON COLUMN dim_member_card_account.member_mobile IS '持卡会员手机号快照。 | 来源: member_mobile';
+COMMENT ON COLUMN dim_member_card_account.balance IS '当前余额或额度。对储值卡表示余额,对其他卡表示剩余金额或次数。 | 来源: balance';
+COMMENT ON COLUMN dim_member_card_account.start_time IS '卡片有效期开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_member_card_account.end_time IS '卡片有效期结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_member_card_account.last_consume_time IS '最近一次消费时间;若为 "1970-01-01" 表示未消费过。 | 来源: last_consume_time';
+COMMENT ON COLUMN dim_member_card_account.status IS '卡状态:1=正常可用;4=过期/停用。其他值在数据中未出现。 | 来源: status';
+COMMENT ON COLUMN dim_member_card_account.is_delete IS '逻辑删除标记:0=未删除;1=已删除。 | 来源: is_delete';
+
+-- dim_member_card_account_Ex
+CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
+ member_card_id BIGINT,
+ site_name TEXT,
+ tenant_name VARCHAR(64),
+ tenantAvatar TEXT,
+ effect_site_id BIGINT,
+ able_cross_site INTEGER,
+ card_physics_type INTEGER,
+ card_no TEXT,
+ bind_password TEXT,
+ use_scene TEXT,
+ denomination NUMERIC(18,2),
+ create_time TIMESTAMPTZ,
+ disable_start_time TIMESTAMPTZ,
+ disable_end_time TIMESTAMPTZ,
+ is_allow_give INTEGER,
+ is_allow_order_deduct INTEGER,
+ sort INTEGER,
+ table_discount NUMERIC(10,2),
+ goods_discount NUMERIC(10,2),
+ assistant_discount NUMERIC(10,2),
+ assistant_reward_discount NUMERIC(10,2),
+ table_service_discount NUMERIC(10,2),
+ goods_service_discount NUMERIC(10,2),
+ assistant_service_discount NUMERIC(10,2),
+ coupon_discount NUMERIC(10,2),
+ table_discount_sub_switch INTEGER,
+ goods_discount_sub_switch INTEGER,
+ assistant_discount_sub_switch INTEGER,
+ assistant_reward_discount_sub_switch INTEGER,
+ goods_discount_range_type INTEGER,
+ table_deduct_radio NUMERIC(10,2),
+ goods_deduct_radio NUMERIC(10,2),
+ assistant_deduct_radio NUMERIC(10,2),
+ table_service_deduct_radio NUMERIC(10,2),
+ goods_service_deduct_radio NUMERIC(10,2),
+ assistant_service_deduct_radio NUMERIC(10,2),
+ assistant_reward_deduct_radio NUMERIC(10,2),
+ coupon_deduct_radio NUMERIC(10,2),
+ cardSettleDeduct NUMERIC(18,2),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ tableAreaId TEXT,
+ goodsCategoryId TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account_Ex.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account_Ex.site_name IS '门店名称展示字段(全部相同)。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenant_name IS '租户名称(当前导出为空)。 | 来源: tenantName';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenantAvatar IS '租户头像 URL(当前导出为空)。 | 来源: tenantAvatar';
+COMMENT ON COLUMN dim_member_card_account_Ex.effect_site_id IS '卡片限定生效门店 ID。0 表示不限门店,配合 able_cross_site=1 表示全店通用。 | 来源: effect_site_id';
+COMMENT ON COLUMN dim_member_card_account_Ex.able_cross_site IS '是否允许跨门店使用该卡:1=允许跨店;0=仅限开卡门店。 | 来源: able_cross_site';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_physics_type IS '物理卡类型:1=实体/标准卡;其他值未出现,含义未知。 | 来源: card_physics_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_no IS '物理卡号或条码(当前全部为空)。 | 来源: card_no';
+COMMENT ON COLUMN dim_member_card_account_Ex.bind_password IS '卡绑定密码(未启用)。 | 来源: bind_password';
+COMMENT ON COLUMN dim_member_card_account_Ex.use_scene IS '使用场景说明(当前为空)。 | 来源: use_scene';
+COMMENT ON COLUMN dim_member_card_account_Ex.denomination IS '面额或初始储值额度(当前均为 0.0,未启用)。 | 来源: denomination';
+COMMENT ON COLUMN dim_member_card_account_Ex.create_time IS '卡片创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_start_time IS '卡片禁用开始时间,当前为默认值表示未禁用。 | 来源: disable_start_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_end_time IS '卡片禁用结束时间,当前为默认值表示未禁用。 | 来源: disable_end_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_give IS '是否允许转赠给他人:0=不允许;1=允许。 | 来源: is_allow_give';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_order_deduct IS '是否允许在订单层面统一扣款:0=不允许;1=允许。 | 来源: is_allow_order_deduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.sort IS '前端排序序号。 | 来源: sort';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount IS '台费折扣率(折扣百分比,10.0=不打折,9.0=九折等)。当前全部 10.0。 | 来源: table_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount IS '商品折扣率,当前为 10.0 表示无折扣。 | 来源: goods_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount IS '助教服务折扣率,当前为 10.0。 | 来源: assistant_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount IS '助教奖励折扣率,当前为 10.0(未启用)。 | 来源: assistant_reward_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_discount IS '台费服务类折扣率,当前为 10.0。 | 来源: table_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_discount IS '商品服务折扣率,当前为 10.0。 | 来源: goods_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_discount IS '助教服务类折扣率,当前为 10.0。 | 来源: assistant_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_discount IS '使用券的折扣比例(全部 10.0,未使用)。 | 来源: coupon_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount_sub_switch IS '台费折扣叠加开关:1=叠加其他折扣;2=不叠加,仅用卡折扣。 | 来源: table_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_sub_switch IS '商品折扣叠加开关,意义同上。 | 来源: goods_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount_sub_switch IS '助教折扣叠加开关,意义同上。 | 来源: assistant_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount_sub_switch IS '助教奖励折扣叠加开关(未启用)。 | 来源: assistant_reward_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_range_type IS '商品折扣范围类型,未在文档说明具体含义。 | 来源: goods_discount_range_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_deduct_radio IS '台费抵扣比例(百分比)。100.0 表示允许全额抵扣;0=不允许。 | 来源: table_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_deduct_radio IS '商品抵扣比例,意义同上。 | 来源: goods_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_deduct_radio IS '助教抵扣比例,意义同上。 | 来源: assistant_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_deduct_radio IS '台费服务金抵扣比例。 | 来源: table_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_deduct_radio IS '商品服务金抵扣比例。 | 来源: goods_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_deduct_radio IS '助教服务金抵扣比例。 | 来源: assistant_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_deduct_radio IS '助教奖励金抵扣比例(未启用)。 | 来源: assistant_reward_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_deduct_radio IS '券抵扣比例(未启用)。 | 来源: coupon_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.cardSettleDeduct IS '结算时统一扣卡金额配置(当前为 0.0,未使用)。 | 来源: cardSettleDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableCardDeduct IS '台费扣卡金额配置,当前 0.0。 | 来源: tableCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableServiceCardDeduct IS '台费服务金扣卡金额配置。 | 来源: tableServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCarDeduct IS '商品扣卡金额配置。 | 来源: goodsCarDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsServiceCardDeduct IS '商品服务金扣卡金额配置。 | 来源: goodsServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantCardDeduct IS '助教扣卡金额配置。 | 来源: assistantCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantServiceCardDeduct IS '助教服务金扣卡金额配置。 | 来源: assistantServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantRewardCardDeduct IS '助教奖励金扣卡金额配置(未启用)。 | 来源: assistantRewardCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.couponCardDeduct IS '使用券扣卡金额配置。 | 来源: couponCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.deliveryFeeDeduct IS '配送费扣卡金额配置(未启用)。 | 来源: deliveryFeeDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableAreaId IS '可用台区 ID 列表,空表示不限台区。 | 来源: tableAreaId';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCategoryId IS '可用商品分类 ID 列表,空表示不限制商品类别。 | 来源: goodsCategoryId';
+COMMENT ON COLUMN dim_member_card_account_Ex.pdAssisnatLevel IS '允许的陪打助教等级列表,空表示不限。 | 来源: pdAssisnatLevel';
+COMMENT ON COLUMN dim_member_card_account_Ex.cxAssisnatLevel IS '允许的促销助教等级列表,空表示不限。 | 来源: cxAssisnatLevel';
+
+-- dim_tenant_goods
+CREATE TABLE IF NOT EXISTS dim_tenant_goods (
+ tenant_goods_id BIGINT,
+ tenant_id BIGINT,
+ supplier_id BIGINT,
+ category_name VARCHAR(64),
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ goods_name VARCHAR(128),
+ goods_number VARCHAR(64),
+ unit VARCHAR(16),
+ market_price NUMERIC(18,2),
+ goods_state INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods.tenant_id IS '租户/品牌 ID,用于区分不同商户。当前样本中全表同一值,但模型上应作为维表外键,用于关联租户维度。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.supplier_id IS '供应商 ID,用于关联供应商档案维度。当前样本全部为 0,说明门店尚未维护供应商信息或导出视图未包含真实供应商关联,但字段含义明确。 | 来源: supplier_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.category_name IS '商品一级分类名称(可读名称),例如:零食、饮料、香烟、雪糕、小吃、酒水、面、槟榔等。真实分类关联通过 goods_category_id 与 goods_second_category_id 实现,此字段主要用于展示和直观分析。 | 来源: categoryName';
+COMMENT ON COLUMN dim_tenant_goods.goods_category_id IS '商品一级分类 ID。与分类维表(例如 dim_goods_category)关联,构成商品分类的第一层。一个 goods_category_id 对应一个 category_name。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_second_category_id IS '商品二级分类 ID。与分类维表的二级节点关联,用于更细粒度的品类统计。取值数目约十四种,每个值属于某个一级分类之下。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_name IS '商品名称(前台展示名),如 “东方树叶”“红烧牛肉面”“百威 235 毫升”等。当前样本中基本唯一。作为用户认知的主显示名称,用于报表、前台展示、小票打印。 | 来源: goods_name';
+COMMENT ON COLUMN dim_tenant_goods.goods_number IS '商品内部编号或自定义货号。当前样本中各记录不重复,如 “1”“2”“10”“11” 等。可用于与其他系统对接或人工查找,有一定对账和排错价值。 | 来源: goods_number';
+COMMENT ON COLUMN dim_tenant_goods.unit IS '商品计量单位,例如:瓶、包、个、份、根、盒、杯、桶、盘、支等。用于解释数量含义,是销售数量与库存数量的度量单位。 | 来源: unit';
+COMMENT ON COLUMN dim_tenant_goods.market_price IS '商品标价或标准销售单价。例如 2、5、6、8、10、12、15、18、20、28 元。POS 默认销售价格,结算时的基础金额字段。 | 来源: market_price';
+COMMENT ON COLUMN dim_tenant_goods.goods_state IS '商品状态枚举。当前样本全部为 1,推测含义为“正常”“已上架”或“有效”。其他值(数据中未出现)通常表示下架、停用或草稿状态。用于控制商品是否可销售。 | 来源: goods_state';
+COMMENT ON COLUMN dim_tenant_goods.create_time IS '商品档案创建时间,格式为 “YYYY-MM-DD HH:MM:SS”。每条记录唯一。用于增量抽取和审计,也可用于分析商品生命周期。 | 来源: create_time';
+COMMENT ON COLUMN dim_tenant_goods.update_time IS '商品档案最近一次修改时间,可为空(表示自创建后未修改)。用于增量同步、变化跟踪和审计分析。 | 来源: update_time';
+COMMENT ON COLUMN dim_tenant_goods.is_delete IS '逻辑删除标志。枚举:0 表示未删除(有效商品);1 表示已逻辑删除(在前台不再展示)。当前样本全部为 0。用于软删除控制和历史数据保留。 | 来源: is_delete';
+
+-- dim_tenant_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
+ tenant_goods_id BIGINT,
+ remark_name VARCHAR(128),
+ pinyin_initial VARCHAR(128),
+ goods_cover VARCHAR(512),
+ goods_bar_code VARCHAR(64),
+ commodity_code VARCHAR(64),
+ commodity_code_list VARCHAR(256),
+ min_discount_price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ cost_price_type INTEGER,
+ able_discount INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ is_in_site BOOLEAN,
+ able_site_transfer INTEGER,
+ common_sale_royalty INTEGER,
+ point_sale_royalty INTEGER,
+ out_goods_id BIGINT,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods_Ex.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods_Ex.remark_name IS '商品备注名或别名,目前样本中均为空。设计用途为简写名、特殊展示名或内部备注,在当前门店尚未启用。 | 来源: remark_name';
+COMMENT ON COLUMN dim_tenant_goods_Ex.pinyin_initial IS '商品拼音首字母或助记码,用于前台按拼音检索,如 “DFSY,DFSX”“HSNRM,GSNRM”“SP” 等。主要为操作便利,对经营分析影响较小。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_cover IS '商品封面图片 URL,用于前端展示商品图片。多个商品可能共用同一图片。对经营和结算逻辑无直接影响。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_bar_code IS '商品条码(如 EAN 码)。当前样本全部为空。含义明确但尚未使用,未来可用于扫码收银或与第三方商品库对接。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code IS '对外商品编码或系列编码,用于与外部系统或其他内部模块对接。例如 “10000”“100000”“10000028”等。一个编码在多条商品上复用,说明它不是主键而是“系列标识”或“外部编码”。具体业务含义依赖上游系统定义。 | 来源: commodity_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code_list IS '商品编码列表的序列化形式,对应源 JSON 的数组字段(当前每条记录仅一个元素)。设计上支持 “一个商品多个编码” 场景,目前仅为 commodity_code 的冗余表现形式。 | 来源: commodityCode';
+COMMENT ON COLUMN dim_tenant_goods_Ex.min_discount_price IS '商品可售最低价(底价)。部分记录为 0.00,表示未设置底价或沿用系统默认规则。用于限制打折或手动改价的下限,防止亏损销售。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price IS '商品成本价,当前大多数为 0.00,仅少数录入 2.0、2.5、3.0 等。用于成本核算与毛利分析。虽当前门店未完整维护,但字段含义清晰,属于成本分析必备结构。 | 来源: cost_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price_type IS '成本价格类型枚举,用于标识成本价的来源或计算方式。已知取值:1 和 2。常见推测:1 表示手工录入成本;2 表示按最近进货价或加权平均价生成。具体含义需结合系统枚举字典确认。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_discount IS '是否允许该商品参与折扣的标志。已知取值:1。按命名推断枚举约定为:1 表示允许参与打折;0 表示不允许参与打折(当前样本未出现)。配合活动、整单折扣等控制哪些商品可享优惠。 | 来源: able_discount';
+COMMENT ON COLUMN dim_tenant_goods_Ex.sale_channel IS '销售渠道类型枚举。当前样本全部为 1,推测为“线下门店正常销售渠道”。理论上可扩展为不同渠道值,例如外卖、小程序、电商等,用于渠道维度分析。具体枚举说明依赖系统配置。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_warehousing IS '是否纳入库存管理的标志。已知取值:1,表示纳入库存管理;0 则表示不纳入库存管理(虚拟商品等,当前未出现)。本门店所有商品均启用库存管理。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_in_site IS '是否在当前门店启用或上架。当前样本全部为 false。由于该文件是租户级商品档案视图,且 isInSite 全为 false,该字段在本视图的实际含义存在不确定性,可能仅在门店级商品表中才有明确业务意义。 | 来源: isInSite';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_site_transfer IS '是否允许门店间调拨或门店级操作的枚举。已知取值:2 为绝大多数,0 为少数一条。按命名推测大致含义为:2 表示允许调拨或默认允许;0 表示禁止调拨。实际枚举定义需查阅系统配置,当前无法完全确定具体业务规则。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_tenant_goods_Ex.common_sale_royalty IS '普通销售提成或佣金配置字段,单位和含义需结合上游系统(可能为金额或比例)。当前样本全部为 0,说明未启用商品级提成配置。 | 来源: common_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.point_sale_royalty IS '积分销售相关的提成或赠送规则配置字段。当前样本全部为 0,同样未启用该功能。具体数值含义(百分比或固定值)需结合系统定义。 | 来源: point_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.out_goods_id IS '外部系统商品 ID,用于对接第三方平台或统一商品库时作为映射主键。目前样本全部为 0,说明尚未配置外部商品映射,具体对接规则依赖上游系统。 | 来源: out_goods_id';
+
+-- dim_store_goods
+CREATE TABLE IF NOT EXISTS dim_store_goods (
+ site_goods_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ category_level1_name TEXT,
+ category_level2_name TEXT,
+ batch_stock_qty INTEGER,
+ sale_qty INTEGER,
+ total_sales_qty INTEGER,
+ sale_price NUMERIC(18,2),
+ created_at TIMESTAMPTZ,
+ updated_at TIMESTAMPTZ,
+ avg_monthly_sales NUMERIC(18,4),
+ goods_state INTEGER,
+ enable_status INTEGER,
+ send_state INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods.tenant_id IS '租户/品牌 ID,同一品牌下多个门店共享,用于跨门店汇总分析。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.site_id IS '门店 ID,对应门店维度表主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.tenant_goods_id IS '租户级(品牌级)商品 ID,用于关联 dim_tenant_goods,实现跨门店统一商品档案。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_name IS '商品名称,例如“合味道泡面”“地道肠”“茶位费”。 | 来源: goods_name';
+COMMENT ON COLUMN dim_store_goods.goods_category_id IS '商品一级分类 ID,对应商品分类维表主键,与 category_level1_name 一一对应。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_second_category_id IS '商品二级分类 ID,其父分类为 goods_category_id。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.category_level1_name IS '一级分类名称,如“零食”“酒水”“服务费”,用于报表维度展示。 | 来源: oneCategoryName';
+COMMENT ON COLUMN dim_store_goods.category_level2_name IS '二级分类名称,如“面”“洋酒”“纸巾”,用于更细粒度分类分析。 | 来源: twoCategoryName';
+COMMENT ON COLUMN dim_store_goods.batch_stock_qty IS '当前成本批次的库存数量,用于按 cost_price 估算库存价值。 | 来源: batch_stock_quantity';
+COMMENT ON COLUMN dim_store_goods.sale_qty IS '截至导出时的销售数量(件),当前数据中与 total_sales_qty 相同。 | 来源: sale_num';
+COMMENT ON COLUMN dim_store_goods.total_sales_qty IS '累计销售数量;当前导出周期下与 sale_qty 一致,为历史全量口径。 | 来源: total_sales';
+COMMENT ON COLUMN dim_store_goods.sale_price IS '商品标准销售价(挂牌价),单位为元。实际结算可能有折扣或券抵扣。 | 来源: sale_price';
+COMMENT ON COLUMN dim_store_goods.created_at IS '门店商品档案创建时间(在门店建立该商品档案时的时间点)。 | 来源: create_time';
+COMMENT ON COLUMN dim_store_goods.updated_at IS '最近一次修改商品档案的时间(包括价格调整、状态变更等)。 | 来源: update_time';
+COMMENT ON COLUMN dim_store_goods.avg_monthly_sales IS '平均月销量(件/月),由某个统计周期内销售数据折算而来,用于补货和品类管理分析。 | 来源: average_monthly_sales';
+COMMENT ON COLUMN dim_store_goods.goods_state IS '商品基础状态枚举:1=正常状态(主流值),2=特殊状态(如新建未完全启用或停售但未彻底下架,通常伴随 stock=0、days_on_shelf=0)。 | 来源: goods_state';
+COMMENT ON COLUMN dim_store_goods.enable_status IS '档案启用状态:1=启用;2=停用(推测,样本中未出现);控制商品档案是否参与业务处理。 | 来源: enable_status';
+COMMENT ON COLUMN dim_store_goods.send_state IS '销售端可售状态:1=可销售/可下单;其他值可能代表停售或仅内部使用(当前样本全部为 1)。 | 来源: send_state';
+COMMENT ON COLUMN dim_store_goods.is_delete IS '逻辑删除标志:0=未删除(有效档案);1=已删除(逻辑删除,不再参与业务但保留历史引用)。 | 来源: is_delete';
+
+-- dim_store_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
+ site_goods_id BIGINT,
+ site_name TEXT,
+ unit TEXT,
+ goods_barcode TEXT,
+ goods_cover_url TEXT,
+ pinyin_initial TEXT,
+ stock_qty INTEGER,
+ stock_secondary_qty INTEGER,
+ safety_stock_qty INTEGER,
+ cost_price NUMERIC(18,4),
+ cost_price_type INTEGER,
+ provisional_total_cost NUMERIC(18,2),
+ total_purchase_cost NUMERIC(18,2),
+ min_discount_price NUMERIC(18,2),
+ is_discountable INTEGER,
+ days_on_shelf INTEGER,
+ audit_status INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ freeze_status INTEGER,
+ forbid_sell_status INTEGER,
+ able_site_transfer INTEGER,
+ custom_label_type INTEGER,
+ option_required INTEGER,
+ remark TEXT,
+ sort_order INTEGER,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods_Ex.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods_Ex.site_name IS '门店名称,例如“朗朗桌球”,是对 site_id 的冗余展示,方便直接阅读。 | 来源: siteName';
+COMMENT ON COLUMN dim_store_goods_Ex.unit IS '销售计量单位,如“包”“瓶”“个”“份”“杯”等。 | 来源: unit';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_barcode IS '商品条形码,用于扫码销售;当前样本多为空。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_cover_url IS '商品图片 URL,用于前端展示商品图片。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_store_goods_Ex.pinyin_initial IS '商品名称拼音首字母缩写,有时多个别名用逗号分隔,用于按字母快速检索和排序。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_qty IS '当前主单位可用库存数量,以 unit 为单位。 | 来源: stock';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_secondary_qty IS '副单位库存数量;若商品存在双单位(如箱/瓶),用于记录副单位库存;当前门店未启用双单位库存,样本中为 0。 | 来源: stock_A';
+COMMENT ON COLUMN dim_store_goods_Ex.safety_stock_qty IS '安全库存阈值,低于该值时系统可提示补货;当前门店尚未配置,样本中为 0。 | 来源: safe_stock';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price IS '商品单件成本价,单位元;部分商品为 0,表示未录入或由其它模块结转成本。 | 来源: cost_price';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price_type IS '成本类型枚举:1=固定成本价(按 cost_price 计),2=动态成本价(按采购单等方式结转,当前多数仍为暂估)。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_store_goods_Ex.provisional_total_cost IS '当前库存暂估总成本,单位元;通常约等于 batch_stock_qty × cost_price。 | 来源: provisional_total_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.total_purchase_cost IS '当前库存总采购成本,单位元;当前样本中与 provisional_total_cost 相等,为后续精算成本预留。 | 来源: total_purchase_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.min_discount_price IS '最低允许成交价(限价),单位元;收银改价时需保证成交价 ≥ 此值,为 0 时表示未设置限价或由其它规则控制。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_store_goods_Ex.is_discountable IS '是否允许参与折扣的标志:1=允许参与折扣;0=不参与任何折扣策略。当前样本全部为 1。 | 来源: able_discount';
+COMMENT ON COLUMN dim_store_goods_Ex.days_on_shelf IS '商品在架天数或可售天数,大致等于当前时间减去首次上架时间;0 通常表示刚建档或刚启用。 | 来源: days_available';
+COMMENT ON COLUMN dim_store_goods_Ex.audit_status IS '审核状态枚举:2=审核通过(当前唯一值);其他值可能代表待提交、待审核、审核不通过等。 | 来源: audit_status';
+COMMENT ON COLUMN dim_store_goods_Ex.sale_channel IS '销售渠道枚举:当前样本全部为 1 表示线下门店渠道;其他值可用于区分外卖、线上商城等渠道。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_store_goods_Ex.is_warehousing IS '是否纳入库存管理:1=参与库存管理(有出入库流水);0 或其他值可能表示不计库存(样本中全部为 1)。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_store_goods_Ex.freeze_status IS '冻结状态:0=未冻结;非 0 可能表示锁定库存或禁止出库,具体业务规则需系统确认。 | 来源: freeze';
+COMMENT ON COLUMN dim_store_goods_Ex.forbid_sell_status IS '禁止销售状态:1=未禁止,允许销售;2=被禁止销售,即使上架也不能卖(含义基于命名和行业惯例推测)。 | 来源: forbid_sell_status';
+COMMENT ON COLUMN dim_store_goods_Ex.able_site_transfer IS '是否允许跨门店调拨或跨站点共享库存:2=不允许跨店调拨(当前主流值);0=未配置(个别记录),含义为是否参与跨店调拨功能。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_store_goods_Ex.custom_label_type IS '自定义标签类型(基于字段名和取值推测):2=使用自定义标签;1 可能表示使用系统默认标签。具体影响哪些标签功能需业务确认。 | 来源: custom_label_type';
+COMMENT ON COLUMN dim_store_goods_Ex.option_required IS '是否需要额外选项或规格(基于字段名和取值推测):1=不需要额外选项,按单规格销售;其他值可能表示必须选择配料或口味。当前样本全部为 1。 | 来源: option_required';
+COMMENT ON COLUMN dim_store_goods_Ex.remark IS '商品备注,可填写口味说明、供应商信息、注意事项等;当前样本全部为空。 | 来源: remark';
+COMMENT ON COLUMN dim_store_goods_Ex.sort_order IS '前端展示排序权重,控制商品在列表中的显示顺序,具体规则(数值越大还是越小排前)由业务配置决定。 | 来源: sort';
+
+-- dim_goods_category
+CREATE TABLE IF NOT EXISTS dim_goods_category (
+ category_id BIGINT,
+ tenant_id BIGINT,
+ category_name VARCHAR(50),
+ alias_name VARCHAR(50),
+ parent_category_id BIGINT,
+ business_name VARCHAR(50),
+ tenant_goods_business_id BIGINT,
+ category_level INTEGER,
+ is_leaf INTEGER,
+ open_salesman INTEGER,
+ sort_order INTEGER,
+ is_warehousing INTEGER,
+ PRIMARY KEY (category_id)
+);
+COMMENT ON COLUMN dim_goods_category.category_id IS '分类节点主键。来自分类树节点的 id,在整个商品分类维度内唯一。用于在事实表中作为商品分类外键引用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_goods_category.tenant_id IS '租户 ID(商户/品牌 ID)。当前所有节点取值相同,表示同一个租户下的分类树。事实表可通过该字段与租户维度或门店维度间接关联。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_name IS '分类名称。一级大类示例:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。二级子类示例:槟榔、皮头、球杆、其他、饮料、酒水、茶水、咖啡、加料、洋酒、果盘、面、小吃等。用于前台展示和报表按细分类统计。 | 来源: category_name';
+COMMENT ON COLUMN dim_goods_category.alias_name IS '分类别名。当前样例数据全部为空字符串,预留给业务方做简称或别名展示。对现阶段经营分析无影响。 | 来源: alias_name';
+COMMENT ON COLUMN dim_goods_category.parent_category_id IS '父级分类 ID。根节点取值为 0,表示没有父分类;子节点取值为父分类的 id。与 category_id 共同形成树形层级关系。 | 来源: pid | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.business_name IS '业务大类名称。将多个细分类归入同一业务线。观测值与一级大类相同:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。子类的 business_name 继承所属根节点的大类名称。用于按业务线汇总库存和销售。 | 来源: business_name';
+COMMENT ON COLUMN dim_goods_category.tenant_goods_business_id IS '业务大类 ID。每个 business_name 对应唯一一个 tenant_goods_business_id,根节点和其下所有子节点共享同一取值。例如“酒水”大类及其子类饮料、茶水、咖啡、加料、洋酒拥有相同的业务 ID。可作为外键连接“业务线维度表”。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_level IS '分类层级:1 表示一级大类(pid = 0),2 表示二级子类(pid ≠ 0)。方便在报表中区分大类与子类进行分组和展示层级控制。 | 来源: 由 pid 推导';
+COMMENT ON COLUMN dim_goods_category.is_leaf IS '是否叶子节点:1 表示叶子分类(categoryBoxes 为空列表),0 表示非叶子分类(存在子分类)。当前样例数据中,一级大类是非叶子节点,二级分类是叶子节点。用于树状导航或限制只能在叶子分类建商品。 | 来源: 由 categoryBoxes 推导';
+COMMENT ON COLUMN dim_goods_category.open_salesman IS '营业员开关控制。枚举含义根据业务系统定义,一般设计为:1 表示启用营业员/导购相关功能,2 表示关闭或不启用。当前样例所有分类取值为 2,说明这一套分类在库存模块中统一未启用营业员逻辑。对目前的经营分析影响较小。 | 来源: open_salesman';
+COMMENT ON COLUMN dim_goods_category.sort_order IS '分类排序序号。来自 sort 字段,用于前端展示顺序控制,数值越小越靠前。当前大部分分类为 0,仅少数为 1,说明排序配置较为粗略。对指标统计无实质影响。 | 来源: sort';
+COMMENT ON COLUMN dim_goods_category.is_warehousing IS '是否参与库存管理。枚举:1 表示参与库存管理,0 表示不参与(如服务类商品、手工费用)。当前文件中所有分类取值为 1,表示这一份分类树只包含“走库存”的商品分类。可在库存报表中用作过滤条件。 | 来源: is_warehousing';
+
+-- dim_groupbuy_package
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
+ groupbuy_package_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ package_name VARCHAR(200),
+ package_template_id BIGINT,
+ selling_price NUMERIC(10,2),
+ coupon_face_value NUMERIC(10,2),
+ duration_seconds INTEGER,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ table_area_name VARCHAR(100),
+ is_enabled INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ tenant_table_area_id_list VARCHAR(512),
+ card_type_ids VARCHAR(255),
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_id IS '租户(品牌/商户)ID。本数据集中全表相同,表示同一品牌。 | 来源: tenant_id | 角色: 外键(指向租户维)';
+COMMENT ON COLUMN dim_groupbuy_package.site_id IS '门店 ID,本表所有记录属于同一门店。与其他 JSON 的 site_id 一致。 | 来源: site_id | 角色: 外键(指向门店维)';
+COMMENT ON COLUMN dim_groupbuy_package.package_name IS '团购套餐名称,用于前台展示及核销界面,例如“早场特惠一小时”“KTV欢唱四小时”等。 | 来源: package_name';
+COMMENT ON COLUMN dim_groupbuy_package.package_template_id IS '上层套餐 ID 或总部/系统级套餐 ID。多个 groupbuy_package_id 可能共享同一个 package_template_id,表示同一业务套餐在不同门店或不同版本下的配置。 | 来源: package_id | 角色: 外键(指向套餐模板维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.selling_price IS '团购售卖价,面向顾客在外部平台的成交价格。当前样本全部为 0,实际平台售价可能在外部系统,不在本地落地。 | 来源: selling_price';
+COMMENT ON COLUMN dim_groupbuy_package.coupon_face_value IS '券面值或内部结算面值。表示此套餐在门店侧可以抵扣的金额,用于验券或套餐流水时记账。例如“早场特惠一小时”可配置为 40.00,“KTV欢唱四小时”可配置为 200.00。当前样本为 0 但字段设计上非常关键。 | 来源: coupon_money';
+COMMENT ON COLUMN dim_groupbuy_package.duration_seconds IS '套餐包含的时长,单位为秒。常见取值:3600 表示 1 小时,7200 表示 2 小时,14400 表示 4 小时。核销时可用于换算可用台费时长。 | 来源: duration';
+COMMENT ON COLUMN dim_groupbuy_package.start_time IS '套餐整体生效开始时间。例如“2025-07-20 00:00:00”。通常从某日零点开始。 | 来源: start_time';
+COMMENT ON COLUMN dim_groupbuy_package.end_time IS '套餐整体生效结束时间。在该时间点之后不可使用。极大日期(如 9999-12-31 23:59:59)可视为长期有效。 | 来源: end_time';
+COMMENT ON COLUMN dim_groupbuy_package.table_area_name IS '套餐适用的门店台区名称,例如“A区中八”“B区中八”“斯诺克”“包厢”“KTV”等。主要用于展示和过滤,配合区域 ID 列实现人类可读的说明。 | 来源: table_area_name';
+COMMENT ON COLUMN dim_groupbuy_package.is_enabled IS '启用状态枚举。1 表示启用或上架;2 表示停用或下架。侧重表示“配置是否上架”,与 effective_status 区分。 | 来源: is_enabled';
+COMMENT ON COLUMN dim_groupbuy_package.is_delete IS '逻辑删除标志。0 表示正常;1 表示逻辑删除(数据仍保留但不再使用)。当前样本全部为 0。 | 来源: is_delete';
+COMMENT ON COLUMN dim_groupbuy_package.create_time IS '套餐配置在系统中的创建时间,用于审计和版本追踪。 | 来源: create_time';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_table_area_id_list IS '租户级台区分组 ID 列表。当前每条记录为一个大整数(例如 2791960001957765)字符串,表示“台区分组”主键。系统通过此分组再关联到具体多个台区。 | 来源: tenant_table_area_id_list | 角色: 外键(指向台区分组维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.card_type_ids IS '允许使用本套餐的会员卡类型 ID 列表。当前样本统一为字符串“0”,表示未限制卡种,任意顾客或任意会员卡都可使用。若未来启用,将以分隔的 ID 列表形式记录限定卡种。 | 来源: card_type_ids | 角色: 外键(潜在指向卡种维)';
+
+-- dim_groupbuy_package_Ex
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
+ groupbuy_package_id BIGINT,
+ site_name VARCHAR(100),
+ usable_count INTEGER,
+ date_type INTEGER,
+ usable_range VARCHAR(255),
+ date_info VARCHAR(255),
+ start_clock VARCHAR(16),
+ end_clock VARCHAR(16),
+ add_start_clock VARCHAR(16),
+ add_end_clock VARCHAR(16),
+ area_tag_type INTEGER,
+ table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_area_id_list VARCHAR(512),
+ group_type INTEGER,
+ system_group_type INTEGER,
+ package_type INTEGER,
+ effective_status INTEGER,
+ max_selectable_categories INTEGER,
+ creator_name VARCHAR(100),
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package_Ex.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.site_name IS '门店名称,当前均为“朗朗桌球”。属于冗余展示字段,可用于报表标题。 | 来源: site_name';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_count IS '可使用次数上限。当前全部为 9999999,用作“无限次使用”的哨兵值。若未来限制次数,只需配置为具体次数。 | 来源: usable_count';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_type IS '日期限制类型枚举。当前样本全部为 1。推测常见含义:1 表示“全部日期可用”;其他值可用于区分工作日、周末或指定日期等模式。 | 来源: date_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_range IS '日期范围说明的文本,例如“周一至周五”等。当前全部为空字符串,实际规则由 date_type 与时间段字段控制。 | 来源: usable_range';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_info IS '更细粒度的日期信息,可能用于存储具体日期列表或节假日规则,形式可能是编码或 JSON 字符串。当前几乎全部为空,仅有极少记录为“0”。 | 来源: date_info';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.start_clock IS '每日可用时间段的起始时间(第一段),字符串格式 HH:MM:SS,例如“10:00:00”“00:00:00”。与 end_clock 组合定义日内时段。 | 来源: start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.end_clock IS '每日可用时间段的结束时间(第一段),字符串格式 HH:MM:SS。与 start_clock 共同描述第一段可用时段。 | 来源: end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_start_clock IS '附加可用时段的起始时间(第二段),格式 HH:MM:SS。当前样本常见值为“00:00:00”或“10:00:00”。用于配置早场加夜场等双时段场景。 | 来源: add_start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_end_clock IS '附加可用时段的结束时间(第二段)。常见值如“1.00:00:00”“18:00:00”“23:59:00”。其中“1.00:00:00”表示跨至次日零点,用于表示“可用到第二天凌晨”的场景。 | 来源: add_end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.area_tag_type IS '区域标记类型枚举。当前样本全部为 1。推测 1 表示“按台区标签限制”(如 A 区、B 区、中八、斯诺克、包厢、KTV 等)。其他取值可能对应按具体台桌或其它规则限用。 | 来源: area_tag_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id IS '单一台区 ID。当前样本全部为 0。原始设计用于限定只能在一个具体区域使用,但由于已引入多选逻辑,实际使用已迁移到 tenant_table_area_id_list。 | 来源: table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.tenant_table_area_id IS '租户级台区 ID,单值版本。当前样本全部为 0。与 table_area_id 类似,已被多选列表字段取代。 | 来源: tenant_table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id_list IS '门店级台区 ID 列表。当前样本全部为空字符串。根据命名推测原本用于存储多个 table_area_id,实际实现已转向租户维度列表字段。 | 来源: table_area_id_list';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.group_type IS '团购类型枚举。当前样本全部为 1。推测 1 表示“计时类/台费类套餐”。其他取值可能用于商品类套餐、代金券类等,需结合系统配置进一步确认。 | 来源: group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.system_group_type IS '系统级团购类型枚举。当前样本全部为 1。推测 1 表示“券码类团购”,即通过券码核销。其他取值可能为卡内套餐、内部套餐等,具体含义有待业务确认。 | 来源: system_group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.package_type IS '内部业务子类型枚举。样本中取值有 1 与 2,各占比不同。具体含义不明,可能区分不同产品线或套餐来源,例如“平台合作套餐”与“自定义套餐”等,需要参考业务文档。 | 来源: type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.effective_status IS '当前有效状态枚举,由系统根据时间及配置动态计算。观测值:1 表示当前有效,可正常核销;3 表示失效或已过期(即使 is_enabled 仍为 1,也不可使用)。可用于分析时过滤失效套餐。 | 来源: effective_status';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.max_selectable_categories IS '最大可选择分类数或子项数,具体含义未在样本和说明中体现,当前值全部为 0。可能用于“组合型套餐”中限制可选项目数量。 | 来源: max_selectable_categories';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.creator_name IS '创建人名称,例如“店长:郑丽珊”。主要用于审计追踪和后台展示。 | 来源: creator_name';
+
+-- dwd_settlement_head
+CREATE TABLE IF NOT EXISTS dwd_settlement_head (
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_name VARCHAR(100),
+ table_id BIGINT,
+ settle_name VARCHAR(100),
+ order_trade_no BIGINT,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ settle_type INTEGER,
+ revoke_order_id BIGINT,
+ member_id BIGINT,
+ member_name VARCHAR(100),
+ member_phone VARCHAR(50),
+ member_card_account_id BIGINT,
+ member_card_type_name VARCHAR(100),
+ is_bind_member BOOLEAN,
+ member_discount_amount NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ pay_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head.tenant_id IS '租户/商户 ID(品牌维度),与各业务 JSON 中的 tenantId 一致。 | 来源: settleList.tenantId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_id IS '门店 ID,用于关联门店维表 dim_site。 | 来源: settleList.siteId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_name IS '门店名称快照,冗余展示字段,推荐通过 site_id 关联维表获取标准名称。 | 来源: settleList.siteName';
+COMMENT ON COLUMN dwd_settlement_head.table_id IS '结账关联的桌台 ID,对应台桌维表 dim_site_table 的主键。 | 来源: settleList.tableId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.settle_name IS '结账对象名称,一般为 “区域 + 桌号”,如 “A区 A17”,便于报表展示。 | 来源: settleList.settleName';
+COMMENT ON COLUMN dwd_settlement_head.order_trade_no IS '交易号 / 订单流水号,与台费、助教等明细中的 order_trade_no 一致,用于按“交易维度”串联各业务明细。 | 来源: settleList.settleRelateId';
+COMMENT ON COLUMN dwd_settlement_head.create_time IS '结账创建时间(收银端点击“确认结账”的时间),格式:YYYY-MM-DD HH:MM:SS。 | 来源: settleList.createTime';
+COMMENT ON COLUMN dwd_settlement_head.pay_time IS '实际支付完成时间,通常晚于 create_time,用于资金结算及对账分析。 | 来源: settleList.payTime';
+COMMENT ON COLUMN dwd_settlement_head.settle_type IS '结账类型枚举。样本中主要有:1=正常结账;3=特殊类型结账(如挂账、补单、调整单等,具体需业务确认)。 | 来源: settleList.settleType';
+COMMENT ON COLUMN dwd_settlement_head.revoke_order_id IS '若当前记录属于撤销链路,记录对应的撤销单或原单的结账 ID,形成自关联关系。样本中为 0。 | 来源: settleList.revokeOrderId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_id IS '会员主键 ID,一般对应租户维度的会员 ID,用于关联 dim_member。 | 来源: settleList.memberId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_name IS '会员姓名快照,冗余展示字段;当前样本多为空,推荐通过关联会员维表获取标准姓名。 | 来源: settleList.memberName';
+COMMENT ON COLUMN dwd_settlement_head.member_phone IS '会员手机号快照,冗余展示字段,通常通过会员维表获取更可靠。 | 来源: settleList.memberPhone';
+COMMENT ON COLUMN dwd_settlement_head.member_card_account_id IS '会员卡账户 ID,对应 dim_member_card_account 主键;当前样本多为 0,但结构上是“结账 → 具体卡账户”的外键。 | 来源: settleList.tenantMemberCardId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_card_type_name IS '会员卡类型名称快照,如“储值卡”“次卡”等,便于前端展示和报表查看。 | 来源: settleList.memberCardTypeName';
+COMMENT ON COLUMN dwd_settlement_head.is_bind_member IS '本单是否绑定会员。0=否(散客);1=是(存在 member_id)。样本中多为 0。 | 来源: settleList.isBindMember';
+COMMENT ON COLUMN dwd_settlement_head.member_discount_amount IS '会员折扣产生的优惠金额(元),例如会员卡折扣减免的台费/商品金额,参与整单优惠拆分。 | 来源: settleList.memberDiscountAmount';
+COMMENT ON COLUMN dwd_settlement_head.consume_money IS '本次结账消费总额(原价小计),约等于台费 + 商品 + 助教 + 服务等项目原价金额之和,未扣除任何优惠。 | 来源: settleList.consumeMoney';
+COMMENT ON COLUMN dwd_settlement_head.table_charge_money IS '本单台费(桌台计费部分)的金额(原价侧)。 | 来源: settleList.tableChargeMoney';
+COMMENT ON COLUMN dwd_settlement_head.goods_money IS '本单商品销售原价金额,对应酒水、小吃等商品类消费。 | 来源: settleList.goodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.real_goods_money IS '商品实际计入金额,通常为 goods_money 扣除部分促销/折扣之后的金额。 | 来源: settleList.realGoodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_pd_money IS '助教“排钟 / 点钟 / 按时长服务”等项目的应计金额(原价侧),与助教流水中的 ledger_amount 汇总对应。 | 来源: settleList.assistantPdMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_cx_money IS '助教“超休”类助教项目金额(原价侧),是对助教收入的补充拆分维度,具体业务定义需结合助教模块确认。 | 来源: settleList.assistantCxMoney';
+COMMENT ON COLUMN dwd_settlement_head.adjust_amount IS '手动减免,人工调价金额汇总(整单减免或特殊价格调整),通常正值表示减免额度。 | 来源: settleList.adjustAmount';
+COMMENT ON COLUMN dwd_settlement_head.pay_amount IS '本单顾客“实付金额”(不含券面值这类虚拟抵扣),等于各支付渠道金额之和减去退款等调整。 | 来源: settleList.payAmount';
+COMMENT ON COLUMN dwd_settlement_head.balance_amount IS '从会员储值余额账户中扣除的金额(储值卡消费部分)。 | 来源: settleList.balanceAmount';
+COMMENT ON COLUMN dwd_settlement_head.recharge_card_amount IS '充值卡支付金额(使用充值类卡片余额支付的金额),与储值/充值型卡资金来源相关。 | 来源: settleList.rechargeCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.gift_card_amount IS '礼品卡或代金卡支付金额。 | 来源: settleList.giftCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.coupon_amount IS '本单由优惠券(团购券、代金券等)实际抵扣的金额。 | 来源: settleList.couponAmount';
+COMMENT ON COLUMN dwd_settlement_head.rounding_amount IS '抹零 / 四舍五入产生的金额差值,例如按角、分抹零。 | 来源: settleList.roundingAmount';
+COMMENT ON COLUMN dwd_settlement_head.point_amount IS '积分相关金额或数量。根据系统配置可能表示“使用积分抵扣的金额”或“本单获得的积分折算金额”,文档未给出唯一定义。 | 来源: settleList.pointAmount';
+
+-- dwd_settlement_head_Ex
+CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
+ order_settle_id BIGINT,
+ serial_number INTEGER,
+ settle_status INTEGER,
+ can_be_revoked BOOLEAN,
+ revoke_order_name VARCHAR(100),
+ revoke_time TIMESTAMPTZ,
+ is_first_order BOOLEAN,
+ service_money NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ payment_method INTEGER,
+ coupon_sale_amount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ is_activity BOOLEAN,
+ operator_name VARCHAR(100),
+ salesman_name VARCHAR(100),
+ order_remark VARCHAR(255),
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.serial_number IS '结账序列号或打印序号,当前样本全部为 0,具体业务用途未在文档中明确。 | 来源: settleList.serialNumber';
+COMMENT ON COLUMN dwd_settlement_head_Ex.settle_status IS '结账状态枚举。当前样本值均为 2,表示“已结算/已完成”;其他取值及含义未在样本和文档中出现,需后续补充。 | 来源: settleList.settleStatus';
+COMMENT ON COLUMN dwd_settlement_head_Ex.can_be_revoked IS '本单是否仍允许撤销/冲正。0=否;1=是。样本中均为 0。主要用于运维控制,分析价值有限。 | 来源: settleList.canBeRevoked';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_order_name IS '撤销单名称/标识,用于人工识别撤销关系;当前样本为空。 | 来源: settleList.revokeOrderName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_time IS '撤销时间。无撤销时通常为系统默认值(如 0001-01-01 00:00:00)。 | 来源: settleList.revokeTime';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_first_order IS '是否首单(新客首单)标记。0=否;1=是。当前样本全部为 0,且文档中说明为“推测用途”,具体业务定义需确认。 | 来源: settleList.isFirst';
+COMMENT ON COLUMN dwd_settlement_head_Ex.service_money IS '其他服务费金额(如包间服务费等),用于与台费、商品、助教金额区分。 | 来源: settleList.serviceMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.cash_amount IS '现金支付金额。 | 来源: settleList.cashAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.card_amount IS '刷卡类支付金额(如银行卡/信用卡等),具体包含哪些通道需结合支付模块确认。 | 来源: settleList.cardAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.online_amount IS '线上支付金额汇总(如微信、支付宝、云闪付等),不区分具体通道。 | 来源: settleList.onlineAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.refund_amount IS '本单涉及的退款金额(元)。普通正常结账为 0,退单或部分退款时为正数。 | 来源: settleList.refundAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.prepay_money IS '本单使用的预付金/定金金额。 | 来源: settleList.prepayMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.payment_method IS '支付方式整体标记(枚举)。当前样本值统一为 0,具体各枚举值对应的支付方式未在文档中说明,需业务确认。 | 来源: settleList.paymentMethod';
+COMMENT ON COLUMN dwd_settlement_head_Ex.coupon_sale_amount IS '优惠券本身的售卖金额/成本金额(例如顾客为购买套餐券支付的金额),当前样本多为 0。 | 来源: settleList.couponSaleAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.all_coupon_discount IS '所有券类优惠折扣的汇总金额,用于统计“券优惠总额”。 | 来源: settleList.allCouponDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.goods_promotion_money IS '商品促销产生的优惠金额(如满减、买赠均摊到商品部分)。 | 来源: settleList.goodsPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_promotion_money IS '助教项目参与活动/促销产生的优惠金额。 | 来源: settleList.assistantPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.activity_discount IS '整单活动折扣金额(如整单打折、满减活动产生的优惠),不区分具体项目类别。 | 来源: settleList.activityDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_manual_discount IS '针对助教服务的人工减免金额,与一般商品/台费折扣区分开。 | 来源: settleList.assistantManualDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_price IS '积分抵扣对应的金额(售价侧),记录因积分使用而减少的应收金额。 | 来源: settleList.pointDiscountPrice';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_cost IS '积分抵扣对应的成本金额(成本侧),用于毛利和利润分析。 | 来源: settleList.pointDiscountCost';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_coupon IS '是否使用优惠券。0=未使用;1=使用。当前样本均为 0。 | 来源: settleList.isUseCoupon';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_discount IS '是否使用折扣(包括会员折扣或其他整单折扣)。0=未使用;1=使用。当前样本多为 0。 | 来源: settleList.isUseDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_activity IS '是否参与营销活动。0=未参与;1=参与。 | 来源: settleList.isActivity';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_name IS '结账操作员名称快照(通常带角色前缀,如“收银员:张三”),用于报表展示。 | 来源: settleList.operatorName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_name IS '营业员/业务员名称,用于业绩归属及提成分析;样本中多为空。 | 来源: settleList.salesManName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_remark IS '订单备注,由收银员手工填写的文字说明,如特殊情况、赠送原因等,主要用于人工复盘。 | 来源: settleList.orderRemark';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_id IS '结账操作员用户 ID,用于关联员工/账号维度(如 dim_staff)。 | 来源: settleList.operatorId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_user_id IS '营业员用户 ID,可关联员工维度,用于业绩分析和提成计算。 | 来源: settleList.salesManUserId | 角色: 外键';
+
+-- dwd_table_fee_log
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
+ table_fee_log_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ member_id BIGINT,
+ ledger_name VARCHAR(64),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ real_table_charge_money NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ real_table_use_seconds INTEGER,
+ add_clock_seconds INTEGER,
+ start_use_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log.order_trade_no IS '订单交易号。整笔订单的主编号,用于把同一订单下的台费、商品、助教等多种明细串联在一起。可与支付记录中的交易号对应。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_settle_id IS '结算单号 / 结账 ID。对应一次完整的结账操作。与 dwd_settlement_head 的主键关联。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_pay_id IS '订单支付记录 ID。对应支付记录中的 id 或 relate_id(视具体模型)。用于追踪这条台费最终对应哪一条支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_id IS '租户 / 品牌 ID。本文件内所有记录属于同一租户。与其他表的 tenant_id 一致,用于品牌级过滤。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_id IS '门店 ID。当前样本为同一门店。与嵌套的 siteProfile.id 以及其他 JSON 中的 site_id 对应,用于门店维度关联。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_id IS '桌台 ID。对应“台桌基础表”的主键。用于确定具体哪一张台或包厢。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_id IS '门店内“台桌区域” ID(门店视角的区域,如 A 区、B 区、斯诺克区、包厢区)。与门店内部的区域维度对应。 | 来源: site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_name IS '台桌区域名称,如 “A区”“B区”“斯诺克区”“VIP包厢” 等。主要用于报表展示和人工阅读。 | 来源: site_table_area_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_table_area_id IS '租户层面的台桌区域 ID。用于品牌层统一定义的区域配置(一个区域可在多门店复用)。对应租户级区域维度。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.member_id IS '会员 ID。多数为 0 表示散客。非 0 时表示关联会员:0 表示散客或未使用会员;>0 对应会员档案中的 id。用于将台费流水关联到 dim_member。 | 来源: member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_name IS '台号名称,例如 “A1”“A2”“S1”“VIP包厢” 等。等价于桌台维表中的展示名称,冗余在流水中作为快照。 | 来源: ledger_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_unit_price IS '台费结算时的计费单价(元/小时或元/单位时长)。与 ledger_count 配合计算原始应收台费。常见值如 48.0、58.0、68.0、88.0、98.0、116.0 等。 | 来源: ledger_unit_price | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_count IS '计费时长单位数。与 ledger_unit_price 共同决定原始应收额。可与 real_table_use_seconds 换算关系约为:时长秒数 ≈ ledger_count × 计费粒度(例如 30 分钟、60 分钟)。 | 来源: ledger_count | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_amount IS '原始应收台费金额,按单价与计费时长计算出来的台费金额,尚未考虑会员、券、调账等各类优惠拆分。 | 来源: ledger_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_charge_money IS '实际向顾客收取的台费金额(现金 / 实付维度),不含券方承担、会员承担和内部调账部分。若为 0,则该笔台费完全由券、会员或内部调账承担。 | 来源: real_table_charge_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.coupon_promotion_amount IS '由优惠券、活动、团购等促销承担的优惠金额,直接抵扣在台费上。常见值为与单价或整倍数相同,例如 48.0、96.0、136.0、144.0 等。若 real_table_charge_money 为 0 且该字段等于 ledger_amount,说明台费完全由促销承担。 | 来源: coupon_promotion_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.member_discount_amount IS '由会员权益产生的优惠金额,例如会员折扣、会员免费台等。若 ledger_amount = real_table_charge_money = member_discount_amount,表示这笔台费由会员权益承担,但仍作为台费收入进行记录。 | 来源: member_discount_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.adjust_amount IS '手动减免,调整金额 / 调账金额。用于将台费金额转移或冲减到其他项目(例如套餐、包厢统一计费)或做手工调整。若 ledger_amount 完全被 adjust_amount 抵消,则说明该笔台费被整体调出当前台费科目。 | 来源: adjust_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_use_seconds IS '台费实际计费时长(秒)。用于计算台费单价与费率分析。内部统一以秒为单位。 | 来源: real_table_use_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.add_clock_seconds IS '加钟时长(秒)。在原有使用基础上追加的累计加钟时长,常见为 2400、4200 等 60 的倍数(对应 40 分钟、70 分钟等)。 | 来源: add_clock_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.start_use_time IS '台开始使用时间,即实际开台时间。与 ledger_start_time 相同,表示计费起算点。 | 来源: start_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_end_time IS '台账计费结束时间。通常与 last_use_time 相差 1 秒。可理解为系统为计费进行的截断时刻。 | 来源: ledger_end_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.create_time IS '台费流水记录创建时间,通常接近结账时间。用于区分计费期间与结账时间。 | 来源: create_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_status IS '台费状态。样本中全部为 1。含义:1 表示正常已结算台费。按命名推断,0 可能表示未结算,2 可能表示作废或撤销,需要结合后续数据确认。 | 来源: ledger_status | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_single_order IS '是否独立计费单元。枚举:1 表示该记录是独立结算的桌费;0 表示非独立结算条目(可能是合并结账、转台过程中的占位记录)。is_single_order = 0 的记录通常 ledger_count 与 real_table_use_seconds 为 0。 | 来源: is_single_order | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_delete IS '逻辑删除标志。0 表示未删除(有效记录);1 表示已逻辑删除(一般不参与统计)。当前样本全部为 0。 | 来源: is_delete | 角色: 无';
+
+-- dwd_table_fee_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
+ table_fee_log_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_name VARCHAR(64),
+ used_card_amount NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ ledger_start_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ salesman_org_id BIGINT,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log_Ex.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_name IS '操作员姓名。为冗余展示字段,便于直接阅读而不必联表员工档案。 | 来源: operator_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_name IS '营业员姓名。当前样本为空。用于需要对营业员维度做业绩统计时作为冗余展示。 | 来源: salesman_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.used_card_amount IS '由储值卡、次卡等“卡内余额”直接抵扣到台费的金额。当前样本为 0,但语义明确,用于区分“卡扣款”与“现金收款”。 | 来源: used_card_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.service_money IS '服务费 / 成本 /分成金额字段,类似助教流水里的 service_money。当前样本全为 0,门店未启用该字段,未来可能用于台费附加服务费或分成计算。 | 来源: service_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.mgmt_fee IS '管理费字段。当前样本为 0。推测用于未来支持“台费附加管理费”功能。尚未实际启用。 | 来源: mgmt_fee | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.fee_total IS '附加费用合计值字段。当前样本为 0。设计上用于汇总管理费、服务费等附加费用。尚未实际启用。 | 来源: fee_total | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.ledger_start_time IS '台账计费起始时间。当前样本与 start_use_time 相同,表示计费与开台同时开始。 | 来源: ledger_start_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.last_use_time IS '最后使用 / 操作时间,通常略晚于 ledger_end_time。可视为客人最后一次用台或最后一次加钟/操作的时间点。 | 来源: last_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_id IS '操作员 ID。负责开台 / 结账的员工账号 ID。与员工 / 账号体系中的用户 ID 对应。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_user_id IS '营业员用户 ID。目前样本值为 0,表示门店暂未使用此字段做提成员工归属,但语义清晰。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_org_id IS '营业员所属机构 / 部门 ID。目前样本为 0。用于员工组织结构统计时的归属。 | 来源: salesman_org_id | 角色: 外键';
+
+-- dwd_table_fee_adjust
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
+ table_fee_adjust_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ ledger_amount NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ adjust_time TIMESTAMPTZ,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_trade_no IS '订单交易号;与台费流水、结账记录等表中的同名字段一致,用于把本次台费调整挂到具体订单上。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_settle_id IS '结算单 / 小票 ID;与小票、结账头表中的 order_settle_id 对应,用于关联同一次结账。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_id IS '租户 / 品牌 ID;标识该记录属于哪一个商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.site_id IS '门店 ID;与 dim_site、其它业务事实表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_id IS '台桌 ID;与 dim_table(site_tables_master.id)以及各类台费、助教流水中的 site_table_id 对应,标识哪一张台发生了折扣/调账。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_id IS '门店维度的台桌区域 ID;与 dim_table 中的 site_table_area_id 对应,例如 “斯诺克区”“VIP包厢”等区域。 | 来源: tableProfile.site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_name IS '台桌区域名称快照,例如 “斯诺克区”“A区”“VIP包厢”;冗余展示字段,可从 dim_table 通过 table_area_id 获取。 | 来源: tableProfile.site_table_area_name';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_table_area_id IS '租户维度的“台桌区域 ID”;同一租户下跨门店复用的区域标识,用于在租户级别统计各区域的折扣分布。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_amount IS '台费调整金额;等于台费流水中对应记录的 adjust_amount。正数表示被减免/调账掉的台费金额(本批数据全部为正);是衡量台费折扣规模的核心度量。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_status IS '调整记录状态(枚举)。1:生效调整(当前有效的折扣/调账记录);0:失效/被覆盖的历史记录(同一订单有多次调整时,旧记录会标记为 0,仅最新一条为 1)。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_table_fee_adjust.is_delete IS '逻辑删除标记(枚举)。0:未删除(有效记录);1:已逻辑删除(后台标记删除,不再参与业务统计)。当前数据全部为 0,但字段需保留以适配长期数据。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_table_fee_adjust.adjust_time IS '台费调整记录创建时间,即打折/调账操作被系统写入的时间戳,用于时间分析和与结账时间对比(判断是事前折扣还是事后调账)。 | 来源: create_time';
+
+-- dwd_table_fee_adjust_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
+ table_fee_adjust_id BIGINT,
+ adjust_type INTEGER,
+ ledger_count INTEGER,
+ ledger_name VARCHAR(128),
+ applicant_name VARCHAR(64),
+ operator_name VARCHAR(64),
+ applicant_id BIGINT,
+ operator_id BIGINT,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.adjust_type IS '调整类型(枚举)。当前数据全部为 1。取值示例:1:台费打折 / 台费减免(本门店实际使用的唯一类型);其他值:预留给台费转移、误操作恢复等其他类型(当前未出现,仅推测)。 | 来源: adjust_type';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_count IS '调整次数计数,本数据中恒为 1,表示“一次调整事件”;与台费流水中的 ledger_count(计时长)含义不同。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_name IS '调账项目名称或打折原因名称(设计意图);当前门店所有记录值为空字符串,未实际使用。作用暂不明确,保留以备后续业务启用。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_name IS '申请人姓名快照,通常包含角色前缀(如 “收银员:张三”);是 applicant_id 的冗余展示字段,实际名称应以员工维表为准。 | 来源: applicant_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_name IS '操作员姓名快照;与 operator_id 对应的姓名冗余字段。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_id IS '申请人 ID;发起本次台费折扣/调账的员工账号 ID,用于按员工维度统计折扣行为。 | 来源: applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_id IS '实际执行调账操作的操作员 ID;当前样本中与 applicant_id 相同,但模型上允许“申请人 ≠ 操作人”。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_store_goods_sale
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
+ store_goods_sale_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_goods_id BIGINT,
+ site_id BIGINT,
+ tenant_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ site_table_id BIGINT,
+ ledger_name VARCHAR(200),
+ ledger_group_name VARCHAR(100),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (store_goods_sale_id)
+);
+COMMENT ON COLUMN dwd_store_goods_sale.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_trade_no IS '订单交易号(业务单号);与台费、助教、团购等表的 order_trade_no 一致,用于把同一订单下各类消费串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_settle_id IS '结账记录主键 ID;连接结账记录 / 结算头事实表。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_pay_id IS '支付记录 ID;连接支付流水事实表,用于还原本条销售对应的收款信息。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_goods_id IS '当前版本的订单内商品明细 ID;可在订单范围内唯一定位该商品行,用于与小票明细等做行级关联。 | 来源: order_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_id IS '门店 ID(系统主键);与其它流水表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_id IS '租户/品牌 ID;同一品牌下多门店共享同一个 tenant_id。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_goods_id IS '门店级商品 ID;连接门店商品档案 dim_store_goods,与库存变动记录中的 siteGoodsId 一致。 | 来源: site_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_id IS '租户级(品牌级)商品 ID;连接租户级商品档案维度表,一个 tenant_goods_id 在不同门店可对应多个 site_goods_id。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_category_id IS '租户级商品一级分类 ID;连接商品分类维度(如酒水、零食等)。 | 来源: tenant_goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_business_id IS '租户级商品业务大类 ID(更高一层的业务分类,如“零食类”“酒水类”等)。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_table_id IS '球台 ID;非 0 表示该商品在某张台桌上点单,0 表示前台售卖或与台桌无关。连接台桌维度 dim_table。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_name IS '销售项目名称(商品名),如“哇哈哈矿泉水”“地道肠”等;为当时销售时刻的名称快照。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_group_name IS '门店前台菜单分组名称,如“酒水”“零食”“小吃”等;与品牌统一分类是两套维度。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_unit_price IS '结算单价(元/单位);本次销售实际使用的单价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_count IS '销售数量(以商品单位计),如 1、2、6、36 等。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_amount IS '原始应收金额(未考虑任何折扣/抵扣),通常接近 ledger_unit_price × ledger_count。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_store_goods_sale.discount_price IS '折后单价(元/单位);无折扣时等于 ledger_unit_price,有折扣时小于 ledger_unit_price。 | 来源: discount_price';
+COMMENT ON COLUMN dwd_store_goods_sale.real_goods_money IS '本行商品实际入账金额(已考虑折扣及其他抵扣后,实际计入营业额的金额);一定不大于 ledger_amount。 | 来源: real_goods_money';
+COMMENT ON COLUMN dwd_store_goods_sale.cost_money IS '本行商品对应的成本金额,用于毛利和利润分析;源自商品档案成本价及成本核算逻辑。 | 来源: cost_money';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_status IS '销售流水状态:1=正常有效;其他数值(当前数据未出现)一般表示“待结算”“作废”等。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_store_goods_sale.is_delete IS '逻辑删除标志:0=正常有效;1=已删除(仅保留历史,不再参与前端展示及统计)(本批数据全部为 0)。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_store_goods_sale.create_time IS '销售记录创建时间,通常为结账时间或录入时间;用于时间维度分析,与订单层时间字段对齐。 | 来源: create_time';
+
+-- dwd_store_goods_sale_Ex
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
+ store_goods_sale_id BIGINT,
+ legacy_order_goods_id BIGINT,
+ site_name TEXT,
+ legacy_site_id BIGINT,
+ goods_remark TEXT,
+ option_value_name TEXT,
+ operator_name TEXT,
+ open_salesman_flag INTEGER,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ discount_money NUMERIC(18,2),
+ returns_number INTEGER,
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ package_coupon_id BIGINT,
+ order_coupon_id BIGINT,
+ member_coupon_id BIGINT,
+ option_price NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ is_single_order INTEGER,
+ sales_type INTEGER,
+ operator_id BIGINT
+);
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_order_goods_id IS '旧版订单商品明细 ID,兼容字段;当前接口已统一使用 order_goods_id,本批数据全部为 0。 | 来源: orderGoodsId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.site_name IS '门店名称,对 site_id 的冗余文本(例如“朗朗桌球”),用于展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_site_id IS '历史兼容门店 ID;当前接口统一使用 site_id,本批数据 siteId 全部为 0。 | 来源: siteId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.goods_remark IS '商品备注/口味说明/特殊说明;部分记录为空,部分与商品名相同。 | 来源: goods_remark';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_value_name IS '商品选项名称(规格/口味,如大杯/小杯、不加冰等);当前门店未启用多规格,样本中全部为空。 | 来源: option_value_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_name IS '操作员姓名冗余,如“收银员:郑丽珊”;用于展示,不作为关联键。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.open_salesman_flag IS '是否启用营业员机制标志:1=启用营业员/提成体系(需指定 salesman_* 字段);2=未启用营业员体系(本批数据全部为 2)。 | 来源: openSalesman';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_user_id IS '营业员用户 ID(系统账号 ID);当前样本全部为 0,说明门店未启用营业员业绩统计。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_name IS '营业员姓名;当前样本全部为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_role_id IS '营业员角色 ID(例如某角色代码对应“销售员”角色);当前样本全部为 0。 | 来源: salesman_role_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_org_id IS '营业员所属组织/部门 ID;当前样本全部为 0,未启用按组织分组统计。 | 来源: sales_man_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.discount_money IS '本行商品的直接价格优惠金额(打折让利部分);在简单场景下满足:ledger_amount − discount_money ≈ real_goods_money(不含积分、券抵扣)。 | 来源: discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.returns_number IS '退货数量;当前样本全部为 0,如发生退货则记录退回的件数。 | 来源: returns_number';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.coupon_deduct_money IS '优惠券/团购券直接抵扣到本条商品明细上的金额;当前样本为 0,说明券更多在订单级处理。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_discount_amount IS '由会员折扣针对本行商品产生的优惠金额;当前样本全部为 0,折扣通常体现在 discount_money 中。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money IS '由积分抵扣的金额(顾客用积分兑换的抵现金额)。 | 来源: point_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money_cost IS '积分抵扣对应的成本金额(积分成本、营销费用等核算用)。 | 来源: point_discount_money_cost';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.package_coupon_id IS '套餐券 ID;当商品来自套餐拆分或与套餐券关联时,用于追溯对应的套餐业务(当前样本为 0)。 | 来源: package_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.order_coupon_id IS '订单级优惠券 ID;整单使用某张券时,可用于记录该券对本行商品的分摊关系(当前样本为 0)。 | 来源: order_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_coupon_id IS '会员券 ID(如会员专享优惠券);当前样本为 0,为会员权益预留字段。 | 来源: member_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_price IS '商品选项(规格/加料等)的附加价格;当前门店未启用此功能,样本为 0。 | 来源: option_price';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_member_discount_money IS '由会员折扣作用在“选项价格”上的优惠金额;当前样本为 0。 | 来源: option_member_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_coupon_deduct_money IS '由优惠券抵扣“选项价格”的金额;当前样本为 0。 | 来源: option_coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.push_money IS '本行商品对应的提成金额(营业员/业务员提成);当前样本为 0,说明提成体系未启用。 | 来源: push_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.is_single_order IS '是否作为独立明细参与订单结算:1=作为独立明细参与订单;0=在特殊业务中可能合并为打包项目(当前样本全部为 1)。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.sales_type IS '销售类型:1=正常销售(当前样本全部为 1);常见扩展用法:2=赠品;3=内部消耗;4=盘点调整等。 | 来源: sales_type';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_id IS '操作员 ID(录入本条销售的员工);与其它流水中的 operator_id 一致,可统一做员工维度分析。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_assistant_service_log
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
+ assistant_service_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INTEGER,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ assistant_no VARCHAR(64),
+ nickname VARCHAR(64),
+ site_assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ person_org_id BIGINT,
+ assistant_level INTEGER,
+ level_name VARCHAR(64),
+ skill_id BIGINT,
+ skill_name VARCHAR(64),
+ ledger_unit_price NUMERIC(10,2),
+ ledger_amount NUMERIC(10,2),
+ projected_income NUMERIC(10,2),
+ coupon_deduct_money NUMERIC(10,2),
+ income_seconds INTEGER,
+ real_use_seconds INTEGER,
+ add_clock INTEGER,
+ create_time TIMESTAMPTZ,
+ start_use_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_trade_no IS '订单交易号,用于与台费、商品、支付等同一订单下的其他明细串联。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_settle_id IS '结算单号,对应结账记录、小票中的结算主键。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_pay_id IS '支付记录主键 ID,用于关联支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_id IS '订单中“助教项目明细”的内部 ID,一笔订单中多段助教服务时用于区分。 | 来源: order_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_type IS '助教服务类型枚举:1 表示常规助教服务(如基础课);2 表示附加类助教服务(如附加课);其他值预留。 | 来源: order_assistant_type';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_id IS '租户/品牌 ID,用于区分商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_id IS '门店 ID,对应门店维表中的门店主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_table_id IS '球台/包厢 ID,对应台桌维表主键。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_member_id IS '商户维度会员 ID,对应会员档案主键;0 表示非会员或散客。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.system_member_id IS '系统级会员 ID,用于跨门店识别同一会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_no IS '助教编号/工号,如 “27”;与助教档案中的工号一致。 | 来源: assistantNo';
+COMMENT ON COLUMN dwd_assistant_service_log.nickname IS '助教对外昵称,如“佳怡”“周周”;用于展示,不参与业务逻辑。 | 来源: nickname';
+COMMENT ON COLUMN dwd_assistant_service_log.site_assistant_id IS '门店维度助教 ID,对应助教账号维表主键。 | 来源: site_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.user_id IS '助教对应的系统用户 ID,对应账号体系中的 user_id。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_team_id IS '助教团队 ID,用于分组统计团队业绩。 | 来源: assistant_team_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.person_org_id IS '助教所属人事组织/部门 ID,如“助教部”;用于组织维度分析。 | 来源: person_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_level IS '助教等级编码:8=助教管理;10=初级;20=中级;30=高级;用于薪酬/评价分层。 | 来源: assistant_level | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.level_name IS '助教等级名称,与 assistant_level 对应,如“初级”“中级”“高级”“助教管理”。 | 来源: levelName';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_id IS '助教服务课程/技能 ID,应对应课程/技能配置表。 | 来源: skill_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_name IS '助教服务课程/技能名称,如“基础课”“附加课”。 | 来源: skillName';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_unit_price IS '助教服务标准单价(原价),例如按小时或按节课的标价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_amount IS '按标准单价计算的应收金额,近似等于 ledger_unit_price×计费时长换算后的金额。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_assistant_service_log.projected_income IS '实际计入门店收入的金额,已经考虑会员权益、券抵扣等后的结果。 | 来源: projected_income';
+COMMENT ON COLUMN dwd_assistant_service_log.coupon_deduct_money IS '由优惠券、团购券等直接抵扣到本次助教服务上的金额;0 表示未使用券。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_assistant_service_log.income_seconds IS '计费秒数(用于计算应收收入的时间长度),通常为按分钟取整的秒数。 | 来源: income_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.real_use_seconds IS '实际服务时长(秒),真实消耗的时间,用于分析助教工作量。 | 来源: real_use_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.add_clock IS '加钟秒数,在原有预约基础上临时增加的服务时间,数值为 60 的倍数。 | 来源: add_clock';
+COMMENT ON COLUMN dwd_assistant_service_log.create_time IS '助教流水记录创建时间,接近下单/结算时间。 | 来源: create_time';
+COMMENT ON COLUMN dwd_assistant_service_log.start_use_time IS '助教实际开始服务时间,通常与 ledger_start_time 一致。 | 来源: start_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.last_use_time IS '助教最后一次服务时间,通常与 ledger_end_time 一致。 | 来源: last_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.is_delete IS '逻辑删除标志:0 未删除;1 已逻辑删除,用于保留历史数据。 | 来源: is_delete';
+
+-- dwd_assistant_service_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
+ assistant_service_id BIGINT,
+ table_name VARCHAR(64),
+ assistant_name VARCHAR(64),
+ ledger_name VARCHAR(128),
+ ledger_group_name VARCHAR(128),
+ ledger_count INTEGER,
+ member_discount_amount NUMERIC(10,2),
+ manual_discount_amount NUMERIC(10,2),
+ service_money NUMERIC(10,2),
+ returns_clock INTEGER,
+ ledger_start_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_confirm INTEGER,
+ is_single_order INTEGER,
+ is_not_responding INTEGER,
+ is_trash INTEGER,
+ trash_applicant_id BIGINT,
+ trash_applicant_name VARCHAR(64),
+ trash_reason VARCHAR(255),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_org_id BIGINT,
+ skill_grade INTEGER,
+ service_grade INTEGER,
+ composite_grade NUMERIC(5,2),
+ sum_grade NUMERIC(10,2),
+ get_grade_times INTEGER,
+ grade_status INTEGER,
+ composite_grade_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.table_name IS '球台名称,如 “A17”“S1”,与 site_table_id 冗余,用于展示。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_name IS '助教姓名,如“何海婷”;与助教档案中的真实姓名一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_name IS '助教计费项目名称,如“2-佳怡”等,通常为展示用组合字段。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_group_name IS '助教项目所属的计费分组/套餐分组名称,目前导出数据中为空,未看到实际使用场景。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_count IS '台账计费时长(秒),通常与 real_use_seconds 接近或相等。取income_seconds TEXT';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.member_discount_amount IS '由会员卡折扣产生的优惠金额,当前样本中为 0,但字段语义明确。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.manual_discount_amount IS '收银员手动减免金额(人工改价);当前导出数据中为 0。 | 来源: manual_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_money IS '与助教结算的金额或服务成本金额,当前数据全部为 0,具体结算规则未见启用。 | 来源: service_money';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.returns_clock IS '退钟秒数(取消加钟或提前结束退回的时间),当前样本中全部为 0,未见业务使用。 | 来源: returns_clock';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_start_time IS '台账计费起始时间。 | 来源: ledger_start_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_end_time IS '台账计费结束时间,可作为本次服务结束时间。 | 来源: ledger_end_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_status IS '助教流水状态:当前数据为 1,表示正常有效;其他值预留给已作废、未结算等状态。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_confirm IS '确认状态:当前样本为 2,一般含义为 1=待确认,2=已确认/已完成(含义基于字段名和现有值推断)。 | 来源: is_confirm';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_single_order IS '是否单独订单:1 表示助教服务作为单独订单结算;0 表示与其他项目合单结算。当前样本全部为 1。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_not_responding IS '是否存在“未响应/爽约”等异常:0 表示正常;1 表示未响应或爽约(基于字段名推断,当前数据均为 0)。 | 来源: is_not_responding';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_trash IS '是否已废除:0 表示正常有效;1 表示已废除,与助教废除记录表(assistant_cancellation_records)对应。 | 来源: is_trash';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_id IS '提出废除申请的员工 ID,用于追溯谁发起了废除操作。 | 来源: trash_applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_name IS '废除申请人姓名,仅用于展示,与 trash_applicant_id 冗余。 | 来源: trash_applicant_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_reason IS '废除原因文案,如“顾客取消”“录入错误”,便于分析异常原因。 | 来源: trash_reason';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_user_id IS '营业员/销售员用户 ID,大多为 0,当前门店未明显使用此维度。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_name IS '营业员/销售员姓名,多数为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_org_id IS '营业员所属组织/部门 ID,多数为 0,尚未看到实际业务使用。 | 来源: salesman_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.skill_grade IS '课程技能评分(整数),当前样本全为 0,评价功能尚未启用。 | 来源: skill_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_grade IS '服务态度评分(整数),当前样本全为 0。 | 来源: service_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade IS '综合评分(技能+服务等加权结果),当前样本为 0。 | 来源: composite_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.sum_grade IS '累计评分总和,用于计算平均分,当前样本为 0。 | 来源: sum_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.get_grade_times IS '获得评价的次数,当前样本为 0。 | 来源: get_grade_times';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.grade_status IS '评价状态枚举:当前样本为 1,一般含义为“未评价/正常”,其他状态未见实际值。 | 来源: grade_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade_time IS '最近一次综合评分时间或评价更新时间,当前为默认时间 “0001-01-01 00:00:00”。 | 来源: composite_grade_time';
+
+-- dwd_assistant_trash_event
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
+ assistant_trash_event_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ assistant_no VARCHAR(32),
+ assistant_name VARCHAR(64),
+ charge_minutes_raw INTEGER,
+ abolish_amount NUMERIC(18,2),
+ trash_reason VARCHAR(255),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event.site_id IS '门店 ID。与其他 JSON 中的 siteId / site_id 含义一致。用来关联 dim_site。当前样例全部为同一门店(朗朗桌球),但设计上支持多门店。 | 来源: siteId | 角色: 外键(指向 dim_site)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_id IS '台桌 ID。对应 site_tables_master.json 中的 id。用于定位哪一张球台发生了助教废除,用于后续软关联台费流水、助教流水时的重要条件。 | 来源: tableId | 角色: 外键(指向 dim_table)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_area_id IS '台桌区域 ID。应与台桌维或区域维中的 area_id 一致,用于按区域统计(A 区/B 区/VIP 包厢等)。 | 来源: tableAreaId | 角色: 外键(潜在指向 dim_table_area)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_no IS '助教编号(工号/序号),如 ''2''、''4''、''27'' 等。与助教档案表 assistant_accounts_master.assistant_no、助教流水中的 assistantNo 一致,用于标识哪位助教。枚举:在门店内是有限编号集合,但并非硬编码含义。 | 来源: assistantOn | 角色: 外键(指向 dim_assistant)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_name IS '助教姓名/昵称,如 “泡芙”“佳怡”等。为冗余展示字段,真实姓名以助教档案为准。当前数据中与档案一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_trash_event.charge_minutes_raw IS '助教被废除前“已计费时长(分钟)”的原始值。单位为分钟。示例:214、3600、10800 等。0 表示尚未发生有效计费就被废除。当前数据中存在异常大值(例如 10800),这一业务含义需结合实际规则理解,但本字段原样保留。枚举:数值型,无固定枚举。 | 来源: pdChargeMinutes';
+COMMENT ON COLUMN dwd_assistant_trash_event.abolish_amount IS '与本次助教废除操作关联的金额,单位元。字面含义为“助教废除金额”。当前样例均为非负数,如 5.83、570.00、0.00 等。正负方向:按照 ODS/JSON 原样保留,暂不在数仓层赋予“收入/支出”的方向含义,后续在 DWS 层按业务规则解释(例如是退还顾客、扣除收益等)。 | 来源: assistantAbolishAmount';
+COMMENT ON COLUMN dwd_assistant_trash_event.trash_reason IS '废除原因的文本说明,例如可以写“顾客临时取消”“误操作”等。当前样例中全部为空字符串,说明前台并未使用该字段。但从结构上看,是一个自由文本字段,不是枚举。 | 来源: trashReason';
+COMMENT ON COLUMN dwd_assistant_trash_event.create_time IS '这条废除记录创建的时间,格式 YYYY-MM-DD HH:MM:SS。代表系统正式记录“废除操作”的时刻,用于和助教服务流水按时间窗口做软关联(结合 site、table、assistant 等条件)。 | 来源: createTime';
+
+-- dwd_assistant_trash_event_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event_Ex (
+ assistant_trash_event_id BIGINT,
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_name IS '台桌名称/编号,便于直观看报表,如 “C1”“B9”“VIP1”等。文案冗余自台桌维度。枚举:在门店范围内是有限集合,但不是固定编码表。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_area_name IS '台桌区域名称(中文),如 “A区”“B区”“C区”“VIP包厢”“补时长”等。展示用文本,具体层级信息由区域维表提供。 | 来源: tableArea';
+
+-- dwd_member_balance_change
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
+ balance_change_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ card_type_id BIGINT,
+ card_type_name VARCHAR(32),
+ member_name VARCHAR(64),
+ member_mobile VARCHAR(20),
+ balance_before NUMERIC(18,2),
+ change_amount NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ from_type INTEGER,
+ payment_method INTEGER,
+ change_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ remark VARCHAR(255),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_id IS '租户/品牌 ID,在整体系统中唯一标识一家商户。当前样本中为同一值。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.site_id IS '本次余额变动发生的门店 ID。通常对应具体门店;样本中:非 0 为“朗朗桌球”,0 代表平台级/虚拟门店场景(如活动抵用券结算)。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.register_site_id IS '办卡门店 ID(卡注册门店)。与 site_id 区分:register_site_id=当初办卡门店,site_id=本次余额变动实际发生门店。当前样本中全部相同。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_id IS '租户维度会员 ID(同一租户内的会员主键),用于关联会员档案。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.system_member_id IS '系统全局会员 ID(跨租户统一的会员标识)。当前只有一个门店,但结构上允许同一人跨租户共享该 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_card_id IS '会员卡账户 ID(租户内唯一的一张具体卡,例如某人的储值卡/酒水卡/台费卡/活动抵用券等)。本次余额变动作用于这张卡。 | 来源: tenant_member_card_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_id IS '卡种类型 ID。与 card_type_name 一一对应,用于区分不同卡种(储值卡/活动抵用券/酒水卡/台费卡)。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_name IS '卡种名称(中文):• 储值卡:通用储值卡;• 活动抵用券:活动送券型卡;• 酒水卡:指定用于酒水类消费;• 台费卡:指定用于台费消费。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_member_balance_change.member_name IS '会员姓名/称呼(如“曾丹烨”“葛先生”“胡先生”),主要用于运营、客服和人工识别。 | 来源: memberName';
+COMMENT ON COLUMN dwd_member_balance_change.member_mobile IS '会员手机号(完整号码字符串),是会员识别、营销触达的重要字段。 | 来源: memberMobile';
+COMMENT ON COLUMN dwd_member_balance_change.balance_before IS '本次变动前的卡内余额,单位:元。可为 0、数百、数千等。 | 来源: before';
+COMMENT ON COLUMN dwd_member_balance_change.change_amount IS '本次余额变动金额,单位:元:• 正数:余额增加(充值、赠送、调整加款等);• 负数:余额减少(消费扣款、退款冲减、活动抵扣等)。所有记录严格满足:balance_after = balance_before + change_amount(浮点精度内)。 | 来源: account_data';
+COMMENT ON COLUMN dwd_member_balance_change.balance_after IS '本次变动后的卡内余额,单位:元。由 before + account_data 计算而得,在源数据中已给出。 | 来源: after';
+COMMENT ON COLUMN dwd_member_balance_change.from_type IS '余额变动来源类型枚举(控制业务含义与方向):• 1:日常消费扣款 —— change_amount 为负数,payment_method=0,表示用卡支付消费被扣余额;• 3:充值增加 —— change_amount 为正数,payment_method=4,表示顾客通过外部支付为卡充值(扫码、银行卡等);• 4:调整/赠送增加 —— change_amount 为正数,payment_method=3,通常为后台赠送或手工加款;• 7:充值退款 —— change_amount 为负数,remark=''充值退款'',表示对历史充值做退款,以减少卡内余额方式体现;• 9:活动抵用券相关余额冲减 —— change_amount 为负数,卡种为“活动抵用券”,site_id=0,表示活动券额度被扣回或结算;• 2:其他增加 —— 当前仅 1 条正数样本(+1865.80),具体业务类型不明,但可确定为余额增加类。总体上:1/7/9 为减余额类,2/3/4 为加余额类。 | 来源: from_type';
+COMMENT ON COLUMN dwd_member_balance_change.payment_method IS '支付/变动渠道枚举(与源系统支付方式枚举一致):• 0:内部结算/无外部支付 —— 日常消费扣款、内部扣减、退款冲减等场景,新资金流不在本记录中产生;• 3:赠送/后台调整渠道 —— 与 from_type=4 搭配出现,表示此余额增加不是顾客付钱,而是后台发放或内部调账;• 4:充值外部支付渠道 —— 与 from_type=3 搭配出现,代表顾客通过某外部渠道完成充值(具体是微信/支付宝/银行卡等需要结合支付枚举表进一步映射)。 | 来源: payment_method';
+COMMENT ON COLUMN dwd_member_balance_change.change_time IS '余额变动时间(记录创建时间),格式 YYYY-MM-DD HH:MM:SS。通常紧邻实际交易发生时间,用于按时间线分析资金变动。 | 来源: create_time';
+COMMENT ON COLUMN dwd_member_balance_change.is_delete IS '逻辑删除标记:• 0:正常记录(当前样本全部为 0);• 1:逻辑删除(标记为删除但数据库保留,用于追溯)。分析时通常需要过滤掉 is_delete=1 的记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_member_balance_change.remark IS '余额变动备注信息。当前样本中主要为:• 空字符串:无额外说明;• 充值退款:明确标记该条记录为“充值退款”业务,与 from_type=7 完全对应。后续可能出现其他业务备注。 | 来源: remark';
+
+-- dwd_member_balance_change_EX
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
+ balance_change_id BIGINT,
+ pay_site_name VARCHAR(64),
+ register_site_name VARCHAR(64),
+ refund_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change_EX.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.pay_site_name IS '余额变动发生门店名称,对应 site_id 的中文名。示例:朗朗桌球;当 site_id = 0 时通常为空字符串。纯展示冗余。 | 来源: paySiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.register_site_name IS '办卡门店名称,对应 register_site_id 的中文名。当前样本全部为 朗朗桌球,属于冗余展示。 | 来源: registerSiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.refund_amount IS '退款金额字段。在当前样本数据中全部为 0.00,推测用于区分“退回卡内余额”和“原路退回”等更细的退款模式,但目前未启用。 | 来源: refund_amount';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_id IS '操作员 ID,执行本次余额变动操作的员工账号主键。可关联员工/账号维度。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_name IS '操作员名称及职位说明,例如:收银员:郑丽珊、店长:谢晓洪 等,是对 operator_id 的可读冗余。 | 来源: operator_name';
+
+-- dwd_groupbuy_redemption
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
+ redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_charge_seconds INTEGER,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_coupon_id BIGINT,
+ coupon_origin_id BIGINT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ order_coupon_channel INTEGER,
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ promotion_seconds INTEGER,
+ coupon_code VARCHAR(64),
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ ledger_name VARCHAR(128),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_id IS '租户/品牌 ID。与其他表统一的租户标识,用于品牌维度聚合。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.site_id IS '门店 ID。与门店维度及其他业务事实中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_id IS '球台 ID。与台桌维度表中的 id 对应,用于确定具体哪一张球台。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_table_area_id IS '租户级台区组合 ID。与团购套餐定义中的 tenant_table_area_id_list 元素对应,表示该券实际使用时所在的台区组合。用于校验券的适用台区是否匹配实际台桌。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_charge_seconds IS '本次结算中该球台总计计费的秒数(整台计费时间)。当台上除了券覆盖时长之外还有额外计费时间时,该值会大于券核销时长。 | 来源: table_charge_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_trade_no IS '订单交易号。与台费流水、商品销售、助教服务、小票详情等表的 order_trade_no 一致,用于将同一笔结账中的所有明细串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_settle_id IS '结算单 ID。与结账记录和小票详情中的结算主键对应,用于从团购券核销记录跳转到整单结算。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_id IS '订单中的“券使用记录 ID”。与平台或内部券核销表中的主键一致,用于在订单内部定位这条券使用记录。当前与 coupon_origin_id 数值相等。 | 来源: order_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_origin_id IS '上游系统或第三方平台中该券记录的主键 ID。可在平台验券记录中查到券的来源平台、原订单等。当前与 order_coupon_id 数值一致,但语义是“券来源 ID”。 | 来源: coupon_origin_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_activity_id IS '促销活动 ID。每条记录对应一个活动主键,用于识别券所属的促销活动或团购活动。 | 来源: promotion_activity_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_coupon_id IS '团购套餐定义 ID。与 group_buy_packages.json 中的 id 一一对应,表示当前使用的是哪一种团购套餐(例如某款“一小时套餐”“两小时套餐”)。 | 来源: promotion_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_channel IS '券渠道类型枚举。观测值:1(大量记录)、2(少量记录)。用于区分券的来源渠道,例如不同团购平台或内部券。具体数值与渠道名称的映射由业务配置决定。 | 来源: order_coupon_channel | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_unit_price IS '本次券在台费侧对应的标准单价,单位元/小时。典型值如 29.9、39.9、59.9、69.9 等。与门店台费计费规则中的单价相对应,用于计算券对应的金额。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_count IS '本次券实际核销的计费秒数。大部分记录等于 promotion_seconds,少数略小于标准时长,表示这张券只覆盖了本次台费的一部分时长。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_amount IS '本次团购券实际冲抵台费的金额。大部分记录中该值与 coupon_money 相等,少数存在小数差异,来源于按单价与秒数换算的结果。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_money IS '本次核销时,团购券在门店侧对应的金额额度(可抵扣金额)。同一种 promotion_coupon_id 下,该值固定,例如某套餐固定为 48.00 元、某套餐固定为 96.00 元等。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_seconds IS '团购套餐定义的标准时长权益,单位秒。观测枚举值为 3600、7200、14400,分别对应 1 小时、2 小时、4 小时。与团购套餐定义表中的 duration 字段一致。 | 来源: promotion_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_code IS '团购券券码字符串。每条记录一个唯一券码,例如“0107892475999”。用于与平台验券记录、券购买记录等做一一对应,追踪券的全生命周期。 | 来源: coupon_code | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_single_order IS '是否作为单独订单行。观测值:1 为主,表示以独立条目方式结算;0 为个别记录,表示嵌入某种组合结算结构。具体业务含义依赖上层订单结构设计。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_delete IS '逻辑删除标记。0 表示正常记录,1 表示逻辑删除但数据仍保留用于追溯。当前样本全部为 0,用于过滤有效记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_name IS '团购项目记账名称,如“全天A区中八一小时”“B区桌球一小时”“中八、斯诺克包厢两小时”等。通常与团购套餐名称相近,用于报表展示和套餐维度分析。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption.create_time IS '本条团购券核销流水的创建时间,通常即核销时间,格式为“YYYY-MM-DD HH:MM:SS”。用于时间维度分析和数据分区。 | 来源: create_time';
+
+-- dwd_groupbuy_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
+ redemption_id BIGINT,
+ site_name VARCHAR(64),
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ order_pay_id BIGINT,
+ goods_option_price NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ offer_type INTEGER,
+ ledger_status INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ ledger_group_name VARCHAR(128),
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.site_name IS '门店名称。当前样本全部为同一门店,仅作冗余展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_name IS '球台名称或台号。如 A7、A11、B1 等。用于业务报表展示与人工识别。 | 来源: tableName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_area_name IS '台区名称。观测枚举值包括 A区、B区、斯诺克区、麻将房。实际取值随门店台区配置变化。 | 来源: tableAreaName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.order_pay_id IS '支付流水 ID。部分记录为 0,表示未在当前导出范围内关联到具体支付记录。真实含义为“指向支付记录表中的支付流水”。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_option_price IS '商品规格价格,用于商品类促销分摊时使用。当前在团购券核销场景中全部为 0,仅作为结构预留。 | 来源: goodsOptionPrice';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_promotion_money IS '本次券使用中分摊到“商品”部分的促销金额。当前所有记录为 0,说明本门店的团购券未用于商品抵扣。 | 来源: goods_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_service_promotion_money IS '本次券使用中分摊到“台费服务费”部分的促销金额。当前样本全部为 0,结构上用于支持更细粒度的费用拆分。 | 来源: table_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_promotion_money IS '本次券使用中分摊到“助教服务”的促销金额。当前全部为 0,说明团购券尚未用于助教服务的抵扣。 | 来源: assistant_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_service_promotion_money IS '进一步细分助教服务对应的促销金额。当前为 0,仅预留结构以支持复杂场景。 | 来源: assistant_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.reward_promotion_money IS '本次促销中属于“奖励金、积分”等来源的促销金额分摊。当前为 0,预留用于积分或奖励金同时参与活动时的金额拆分。 | 来源: reward_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.recharge_promotion_money IS '来自“充值赠送”等储值优惠的促销金额分摊。当前为 0,预留用于将来区分“券优惠”和“充值赠送优惠”的场景。 | 来源: recharge_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.offer_type IS '优惠类型枚举。当前样本值全部为 1,表示本门店使用的团购券均为同一类型(例如“套餐券”)。其他取值可能对应满减、折扣、代金券等优惠类型,在本数据中未出现。 | 来源: offer_type';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_status IS '流水状态。观测值全部为 1。常规含义为:1 表示正常有效记录;其他值预留用于表示作废、撤销、未生效等状态。当前导出仅包含正常状态记录。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_id IS '执行本次券核销操作的操作员 ID。可与员工维度表对接,用于分析不同操作员的核销行为与绩效。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_name IS '操作员名称及角色说明,例如“收银员:郑丽珊”。与 operator_id 冗余,对报表展示友好,但不参与模型关联。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_user_id IS '营业员用户 ID。当前全部为 0,表示本门店在团购券场景未单独记录营业员信息。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_name IS '营业员姓名。当前为空字符串。结构上用于记录拉单或促销的业务员信息。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_role_id IS '营业员角色 ID。当前为 0,预留用于标识营业员在组织中的角色类型。 | 来源: salesman_role_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_org_id IS '营业员所属组织 ID。来源字段为 sales_man_org_id,DWD 层统一命名为 salesman_org_id。当前为 0,用于将来对接组织架构维度。 | 来源: sales_man_org_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_group_name IS '团购项目的记账分组名称。当前全部为空,预留给将来按团购项目大类分组(例如“团购台费”“团购包厢”)使用。 | 来源: ledger_group_name';
+
+-- dwd_platform_coupon_redemption
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
+ platform_coupon_redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ coupon_code VARCHAR(64),
+ coupon_channel INTEGER,
+ coupon_name VARCHAR(200),
+ sale_price NUMERIC(10,2),
+ coupon_money NUMERIC(10,2),
+ coupon_free_time INTEGER,
+ channel_deal_id BIGINT,
+ deal_id BIGINT,
+ group_package_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ certificate_id VARCHAR(64),
+ verify_id VARCHAR(64),
+ use_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ consume_time TIMESTAMPTZ,
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.tenant_id IS '租户 ID,品牌级别标识。例如整套系统中的“朗朗桌球”品牌。与其他表的 tenant_id 一致,用于划分租户数据域。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于区分不同门店。siteProfile.id 与此字段相同,本表不再冗余门店快照。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_code IS '第三方团购券券码,顾客出示的核销码。当前样本中全表唯一,可视为业务自然主键,用于验券、对账、查询。 | 来源: coupon_code';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_channel IS '券来源渠道枚举,表示第三方平台渠道编号。观测值:1,2。具体含义需结合系统配置,一般可理解为:1 表示平台渠道 1(主平台),2 表示平台渠道 2(其他入口或子平台)。 | 来源: coupon_channel';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_name IS '第三方团购券产品名称,例如“【全天可用】中八桌球一小时(A区)”“1小时中八台球【11月特惠】(A区)”等。用于报表展示和区分不同团购产品。 | 来源: coupon_name';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.sale_price IS '顾客在第三方平台实际支付的团购售价,例如 11.11、29.90、39.90 等。始终小于 coupon_money,体现“折后价”。 | 来源: sale_price';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_money IS '券面值或套餐价值,即系统认为该券可抵扣的金额,例如 48.00、58.00、68.00、96.00、116.00、288.00。与 coupon_name 有固定对应关系。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_free_time IS '券附带的赠送时长,单位:秒。当前样本全部为 0,表示无独立赠送时长。若未来有赠送时间型券,则该字段存储赠送的秒数。 | 来源: coupon_free_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.channel_deal_id IS '渠道侧团购商品 ID(第三方平台 dealId)。值域有限(约 9 个值),与 coupon_name 一一对应。用于对接第三方接口和按平台商品维度统计。 | 来源: channel_deal_id | 角色: - 或 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.deal_id IS '平台/系统侧团购商品 ID。多数记录为非 0 整数,也有部分为 0。与 coupon_name 存在稳定对应关系,0 表示内部未配置或未同步。未来可作为内部团购商品维度外键。 | 来源: deal_id | 角色: 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.group_package_id IS '内部“团购套餐”定义表主键 ID。当前样本中全部为 0,表示平台券尚未映射到自有团购套餐;从设计上是预留的外键字段。 | 来源: group_package_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_order_id IS '门店内部订单 ID。本次平台券核销所挂靠的店内订单号。用于与结账记录、台费流水、商品销售等事实表通过订单维度关联。 | 来源: site_order_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.table_id IS '使用团购券的球台 ID。与 dim_site_table.table_id 对应,用于统计每张球台的第三方平台引流情况。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.certificate_id IS '第三方平台侧券实例 ID(凭证 ID),通常为 16–19 位数字字符串。用于与外部平台对账与查询核销结果。存在重复值,不能单独作为唯一键。 | 来源: certificate_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.verify_id IS '第三方平台核销记录 ID。大部分记录为空,少量有值。存在时可用于精确反查平台侧核销记录。 | 来源: verify_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.use_status IS '券使用状态枚举。观测值:1、2。1 表示已使用/已核销(正常消耗);2 表示已退款/已撤销或使用后反冲的状态。是判断券生命周期状态的核心字段。 | 来源: use_status';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.is_delete IS '逻辑删除标志。0 表示未删除;1 表示已逻辑删除。与 use_status 独立:即便业务状态异常(如 use_status=2),也可能 is_delete 仍为 0 以保留记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.create_time IS '系统记录创建时间,即核销记录写入本系统的时间。格式为 YYYY-MM-DD HH:MM:SS。通常与 consume_time 相差约 1 秒。 | 来源: create_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.consume_time IS '券被核销/使用的业务时间,代表实际团购券使用发生的时间点。后续按核销日期统计核销量时以该字段为准。 | 来源: consume_time';
+
+-- dwd_platform_coupon_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
+ platform_coupon_redemption_id BIGINT,
+ coupon_cover VARCHAR(255),
+ coupon_remark VARCHAR(255),
+ groupon_type INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(50),
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_cover IS '券封面图片地址 URL,用于前端展示团购券图片。对经营分析和结算逻辑无影响。 | 来源: coupon_cover';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_remark IS '券描述或备注信息,用于展示券规则、说明文字。未参与计算和关联逻辑。 | 来源: coupon_remark';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.groupon_type IS '团购券类型枚举。当前样本全部为 1。推断含义:1 表示标准团购券,其他值预留为次卡、套餐券、权益券等类型。 | 来源: groupon_type';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_id IS '执行验券操作的员工/收银员账号 ID。当前样本中多数为同一值。可与员工/账号维度表关联。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_name IS '操作员姓名或显示名,例如“收银员:郑丽珊”。是 operator_id 的冗余展示字段,用于报表展示。 | 来源: operator_name';
+
+-- dwd_recharge_order
+CREATE TABLE IF NOT EXISTS dwd_recharge_order (
+ recharge_order_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ member_id BIGINT,
+ member_name_snapshot TEXT,
+ member_phone_snapshot TEXT,
+ tenant_member_card_id BIGINT,
+ member_card_type_name TEXT,
+ settle_relate_id BIGINT,
+ settle_type INTEGER,
+ settle_name TEXT,
+ is_first INTEGER,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ payment_method INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order.tenant_id IS '租户/品牌 ID;与其他 JSON 中 tenantId 含义一致。 | 来源: tenantId | 角色: 外键(dim_tenant)';
+COMMENT ON COLUMN dwd_recharge_order.site_id IS '门店 ID;与 siteProfile.id 一致,用于关联门店维度。 | 来源: siteId | 角色: 外键(dim_site)';
+COMMENT ON COLUMN dwd_recharge_order.member_id IS '会员 ID;对应会员档案中的 tenantMemberInfos.id。标识给哪个会员充值。 | 来源: memberId | 角色: 外键(dim_member)';
+COMMENT ON COLUMN dwd_recharge_order.member_name_snapshot IS '会员姓名/昵称快照,可能是名称或手机号字符串。 | 来源: memberName';
+COMMENT ON COLUMN dwd_recharge_order.member_phone_snapshot IS '会员手机号快照。 | 来源: memberPhone';
+COMMENT ON COLUMN dwd_recharge_order.tenant_member_card_id IS '会员卡实例 ID(某张具体卡);可关联 dim_member_card_account。 | 来源: tenantMemberCardId | 角色: 外键(dim_member_card_account)';
+COMMENT ON COLUMN dwd_recharge_order.member_card_type_name IS '会员卡类型名称;当前样例主要有:“储值卡”、“月卡”。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_recharge_order.settle_relate_id IS '结算关联 ID;用于与支付记录等跨表关联(类似业务单 ID)。 | 来源: settleRelateId | 角色: 外键(与支付/结算域软关联)';
+COMMENT ON COLUMN dwd_recharge_order.settle_type IS '结算类型枚举:5=“充值订单”(正常充值);7=“充值撤销”(冲销记录)。 | 来源: settleType';
+COMMENT ON COLUMN dwd_recharge_order.settle_name IS '结算类型名称:"充值订单"、"充值撤销";前端展示用。 | 来源: settleName';
+COMMENT ON COLUMN dwd_recharge_order.is_first IS '是否首充标记。取值:1 或 2。理论含义类似“是否首充”,但 1/2 的精确定义需系统字典确认。 | 来源: isFirst';
+COMMENT ON COLUMN dwd_recharge_order.pay_amount IS '本条记录的充值金额(可为正/负):正数=实际充值金额;负数=撤销流水金额(settleType=7)。 | 来源: payAmount';
+COMMENT ON COLUMN dwd_recharge_order.refund_amount IS '对该充值订单的退款金额(通常为正数);原始充值单上为已退款金额,对应会有一条负数的“充值撤销”记录。 | 来源: refundAmount';
+COMMENT ON COLUMN dwd_recharge_order.point_amount IS '计入会员账户的储值/积分金额;多数情况下等于 pay_amount 的绝对值;撤销记录一般为 0。 | 来源: pointAmount';
+COMMENT ON COLUMN dwd_recharge_order.cash_amount IS '现金收款金额;样本中少数为 3000/5000,其余为 0。 | 来源: cashAmount';
+COMMENT ON COLUMN dwd_recharge_order.payment_method IS '支付方式编码。样本取值:1、2、4;具体对应渠道(现金/微信/支付宝/银行卡等)需系统“支付方式字典”确认。 | 来源: paymentMethod';
+COMMENT ON COLUMN dwd_recharge_order.create_time IS '充值记录创建时间(收银完成时间);用于时间分区、统计。 | 来源: createTime';
+COMMENT ON COLUMN dwd_recharge_order.pay_time IS '支付完成时间;通常与 create_time 接近或相同。 | 来源: payTime';
+
+-- dwd_recharge_order_Ex
+CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
+ recharge_order_id BIGINT,
+ site_name_snapshot TEXT,
+ settle_status INTEGER,
+ is_bind_member BOOLEAN,
+ is_activity BOOLEAN,
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ can_be_revoked BOOLEAN,
+ online_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name_snapshot TEXT,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ order_remark TEXT,
+ table_id INTEGER,
+ serial_number INTEGER,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order_Ex.site_name_snapshot IS '门店名称快照,如“朗朗桌球”;仅用于展示,门店改名后本字段不变。 | 来源: siteName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.settle_status IS '结算状态;当前数据全部为 2,推测 2=已完成。其它状态未出现在样本中。 | 来源: settleStatus';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_bind_member IS '是否绑定为会员/其他绑定标记;当前所有记录为 False,而又都有 memberId,实际业务含义不清。 | 来源: isBindMember';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_activity IS '是否关联营销活动;当前全部为 False,表示样本周期内充值未绑定活动。 | 来源: isActivity';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_coupon IS '本次充值是否使用优惠券;当前样本全部为 False。结构上预留“充值用券”的能力。 | 来源: isUseCoupon';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_discount IS '是否使用折扣(如充值折扣);样本中全为 False。 | 来源: isUseDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.can_be_revoked IS '当前记录是否仍可撤销;样本中全为 False(导出时均不可撤销)。 | 来源: canBeRevoked';
+COMMENT ON COLUMN dwd_recharge_order_Ex.online_amount IS '线上支付金额(如微信、支付宝等);当前样本为 0,但字段为支付渠道拆分预留。 | 来源: onlineAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.balance_amount IS '从账户余额中支付的金额;充值场景通常为 0(用余额充值没有实际意义)。 | 来源: balanceAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.card_amount IS '从其他储值卡或某种卡余额支付的金额;当前样本全为 0。 | 来源: cardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_amount IS '使用券直接支付的金额(如储值券);当前样本为 0。 | 来源: couponAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_card_amount IS '充值到卡上的金额(与 point_amount 区分不同资金属性);样本为 0,结构预留。 | 来源: rechargeCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.gift_card_amount IS '赠送卡金额(如买 1000 送 100 的赠送部分);当前样本为 0。 | 来源: giftCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.prepay_money IS '预付款金额(订金);当前样本为 0,充值未启用此场景。 | 来源: prepayMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.consume_money IS '消费总金额;在充值文件中全部为 0,实际用于消费场景(台费/商品)的结算模型复用字段。 | 来源: consumeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_money IS '商品消费金额(充值记录中为 0)。 | 来源: goodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.real_goods_money IS '实际应计商品金额(扣除折扣后);充值记录中为 0。 | 来源: realGoodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_charge_money IS '台费金额;充值记录中为 0,来自通用结算模型。 | 来源: tableChargeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.service_money IS '服务项目金额(如助教、其他服务);充值中为 0。 | 来源: serviceMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.activity_discount IS '营销活动折扣金额;当前样本为 0。 | 来源: activityDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.all_coupon_discount IS '各类优惠券、团购券综合折扣金额;样本为 0。 | 来源: allCouponDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_promotion_money IS '商品促销优惠金额;样本为 0。 | 来源: goodsPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_promotion_money IS '助教相关促销优惠金额;样本为 0。 | 来源: assistantPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_pd_money IS '助教配单金额/相关费用;样本为 0。 | 来源: assistantPdMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_cx_money IS '助教冲销/促销相关金额;样本为 0。 | 来源: assistantCxMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_manual_discount IS '助教手工减免金额;样本为 0。 | 来源: assistantManualDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_sale_amount IS '券/套餐销售金额(售卖券时使用);充值场景中为 0。 | 来源: couponSaleAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.member_discount_amount IS '因会员折扣产生的优惠金额;在充值样本中为 0。 | 来源: memberDiscountAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_price IS '积分抵扣产生的价差(价格部分);样本为 0。 | 来源: pointDiscountPrice';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_cost IS '积分抵扣对应的成本金额;样本为 0。 | 来源: pointDiscountCost';
+COMMENT ON COLUMN dwd_recharge_order_Ex.adjust_amount IS '手工调整金额(非抹零);样本为 0。 | 来源: adjustAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.rounding_amount IS '抹零金额(四舍五入产生的差额);样本为 0。 | 来源: roundingAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_id IS '操作该笔充值的收银员/员工 ID。 | 来源: operatorId | 角色: 外键(将来可关联 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_name_snapshot IS '操作员姓名快照,便于直接阅读;与 operator_id 对应。 | 来源: operatorName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_user_id IS '营业员用户 ID;当前样本全部为 0。 | 来源: salesManUserId | 角色: 外键(潜在 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_name IS '营业员/销售员姓名;样本为空字符串。 | 来源: salesManName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.order_remark IS '充值订单备注,如手工说明;当前样本为空。 | 来源: orderRemark';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_id IS '台桌 ID;充值场景下全部是 0,表示该订单不挂具体球台。 | 来源: tableId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.serial_number IS '流水/小票序号;当前样本全部为 0,本门店未启用。 | 来源: serialNumber';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_id IS '撤销相关订单 ID(被撤销原单或撤销单指针);样本中存在值但逻辑未完全启用。 | 来源: revokeOrderId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_name IS '撤销单名称/说明;样本全为空。 | 来源: revokeOrderName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_time IS '撤销时间;当前样本为空,撤销信息主要通过负数流水与 refund_amount 表达。 | 来源: revokeTime';
+
+-- dwd_payment
+CREATE TABLE IF NOT EXISTS dwd_payment (
+ payment_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ payment_method INTEGER,
+ online_pay_channel INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ pay_date DATE,
+ PRIMARY KEY (payment_id)
+);
+COMMENT ON COLUMN dwd_payment.payment_id IS '支付流水主键ID。与源系统 id 一致。每条支付流水唯一标识一条支付行为(包括金额为 0 的记录)。 | 来源: payment_transactions.id | 角色: 主键';
+COMMENT ON COLUMN dwd_payment.site_id IS '门店ID。当前样本中全部为同一门店 2790685415443269。在数仓中外键关联 dim_site.site_id。 | 来源: payment_transactions.site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_payment.relate_type IS '业务关联类型枚举,用来区分这条支付流水对应哪一类业务单据:• 2:结账单支付,对应结账记录 settlement_records 中的结账单;• 5:会员卡充值/账户变动类支付,对应会员余额/充值业务单号,在会员余额变更或充值结算中复用;• 1:其他业务类型,目前样本中仅有 1 条记录,具体业务含义待业务侧补充。 | 来源: payment_transactions.relate_type | 角色: −';
+COMMENT ON COLUMN dwd_payment.relate_id IS '关联业务记录ID,配合 relate_type 使用,是一个“多态外键”:• 当 relate_type = 2 时:relate_id = settlement_records.settleList.id(结账记录主键,对应 dwd_settlement_head_di.order_settle_id);• 当 relate_type = 5 时:relate_id = 会员卡余额变动/充值业务单号,在会员余额变更流水中同名字段使用;• 当 relate_type = 1 时:关联具体业务尚未确认,仅可视为预留类型。 | 来源: payment_transactions.relate_id | 角色: 外键(多业务类型)';
+COMMENT ON COLUMN dwd_payment.pay_amount IS '本次支付金额,单位元。为收入类字段,当前样本全部为非负数:• 正数:实际通过该支付方式收取的金额;• 0:仍生成支付流水,但实收金额为 0(例如整单由会员优惠、团购券、余额等抵扣),当前样本中有 140 条记录金额为 0。 | 来源: payment_transactions.pay_amount | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_status IS '支付状态枚举。当前样本中仅出现:• 2:支付成功。其它可能的状态(未支付、支付中、失败、已退款等)在本次导出中未出现,需以后按系统支付状态配置补充。由于本 JSON 仅导出成功记录,可以视作“成功支付流水视图”。 | 来源: payment_transactions.pay_status | 角色: −';
+COMMENT ON COLUMN dwd_payment.payment_method IS '支付方式枚举。当前样本中出现的取值:• 2:共 140 条记录;• 4:共 60 条记录。具体取值与“支付方式配置表”对应,例如可能代表现金、扫码支付、银行卡等。由于配置表未导出,在数仓中应作为枚举码字段,通过后续 dim_payment_method 进行解码。不要在数仓层擅自写死“2=微信、4=支付宝”等含义。 | 来源: payment_transactions.payment_method | 角色: 外键(预期关联支付方式维度)';
+COMMENT ON COLUMN dwd_payment.online_pay_channel IS '线上支付通道枚举。用于进一步细分线上渠道,例如:• 0:无线上通道/线下,或未区分具体线上通道(当前样本全部为 0);• 1:微信(推测,未在样本中出现);• 2:支付宝(推测,未在样本中出现)。目前门店在当前时间段内尚未使用该字段进行实际区分,业务含义需结合正式配置确认。 | 来源: payment_transactions.online_pay_channel | 角色: −';
+COMMENT ON COLUMN dwd_payment.create_time IS '支付流水创建时间,格式 YYYY-MM-DD HH:MM:SS。通常是发起支付请求的时间。当前样本中 create_time 与 pay_time 多数相同,但模型上允许两者不同(例如异步支付)。 | 来源: payment_transactions.create_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_time IS '支付完成时间(支付成功时间戳),格式 YYYY-MM-DD HH:MM:SS。用于统计资金实际入账时间,以及与结账时间进行对齐分析。 | 来源: payment_transactions.pay_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_time 截取 YYYY-MM-DD 得到。例如 pay_time = ''2025-11-09 23:35:57'' 时,pay_date = ''2025-11-09''。用于 DWD 表按天分区和日粒度汇总。 | 来源: 由 payment_transactions.pay_time 派生 | 角色: −';
+
+-- dwd_refund
+ CREATE TABLE IF NOT EXISTS dwd_refund (
+ refund_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ channel_fee NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ payment_method INTEGER,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型) | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund.tenant_id IS '租户/品牌 ID,标识所属商户。与其他表中的 tenant_id 一致。 | 来源: tenant_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于分门店分析。 | 来源: site_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.relate_type IS '业务类型枚举,指示本退款对应哪类业务主单:当前样本值 {2, 5}:2=消费/结账类业务;5=充值/储值类业务(具体定义以业务字典为准)。与 relate_id 组合使用。 | 来源: relate_type';
+ COMMENT ON COLUMN dwd_refund.relate_id IS '关联的业务主键 ID,含义依赖 relate_type:relate_type=2 时通常指结账主单 ID;relate_type=5 时通常指充值/储值业务单 ID。同一个 relate_id 可能有多笔退款(分批退款)。 | 来源: relate_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.pay_amount IS '本次退款的资金金额,统一为负数。绝对值即退款金额,例如 -5000.00 表示退款 5000 元。 | 来源: pay_amount';
+ COMMENT ON COLUMN dwd_refund.channel_fee IS '第三方支付渠道对本次退款收取的手续费。当前样本为 0.00,用于通道成本核算。 | 来源: channel_fee';
+ COMMENT ON COLUMN dwd_refund.pay_time IS '退款在支付渠道/系统中发生的时间(退款完成时间),用于对账及按时间统计。 | 来源: pay_time';
+ COMMENT ON COLUMN dwd_refund.create_time IS '本条退款流水在系统内创建时间,用于区分记录生成时间与渠道时间。 | 来源: create_time';
+ COMMENT ON COLUMN dwd_refund.payment_method IS '支付方式枚举,指本次退款对应的原支付方式(如通道)。样本出现值 4,支付记录中有 {2,4},具体含义需参照支付方式配置表。 | 来源: payment_method';
+ COMMENT ON COLUMN dwd_refund.member_id IS '关联的会员 ID,对应会员档案表主键。样本为 0,表示未绑定会员。 | 来源: member_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.member_card_id IS '关联的会员卡账户 ID,对应会员卡账户/储值卡维度主键。样本为 0,当前没有“退到会员卡”的记录。 | 来源: member_card_id | 角色: 外键';
+
+
+ CREATE TABLE IF NOT EXISTS dwd_refund_Ex (
+ refund_id BIGINT,
+ tenant_name VARCHAR(64),
+ pay_sn BIGINT,
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ action_type INTEGER,
+ is_revoke INTEGER,
+ is_delete INTEGER,
+ check_status INTEGER,
+ online_pay_channel INTEGER,
+ online_pay_type INTEGER,
+ pay_terminal INTEGER,
+ pay_config_id INTEGER,
+ cashier_point_id INTEGER,
+ operator_id BIGINT,
+ channel_payer_id VARCHAR(128),
+ channel_pay_no VARCHAR(128),
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund_Ex.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。 | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund_Ex.tenant_name IS '租户名称,例如“朗朗桌球”。与租户维度中的名称冗余。 | 来源: tenantName';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_sn IS '支付流水内部序号。退款记录中样本全部为 0,未看到实际使用场景,含义未说明。 | 来源: pay_sn';
+ COMMENT ON COLUMN dwd_refund_Ex.refund_amount IS '本次退款金额(正数)设计字段,样本为 0.00,实际使用 pay_amount。 | 来源: refund_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.round_amount IS '退款过程中的舍入/抹零金额。 | 来源: round_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.balance_frozen_amount IS '与会员余额相关的冻结金额,样本为 0。 | 来源: balance_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.card_frozen_amount IS '与某张会员卡余额相关的冻结金额,样本为 0。 | 来源: card_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_status IS '退款状态枚举。样本中全部为 2(成功/已完成)。 | 来源: pay_status';
+ COMMENT ON COLUMN dwd_refund_Ex.action_type IS '资金动作类型枚举。样本全部为 2(退款)。 | 来源: action_type';
+ COMMENT ON COLUMN dwd_refund_Ex.is_revoke IS '是否为撤销型退款:0=正常退款;1=撤销原支付。 | 来源: is_revoke';
+ COMMENT ON COLUMN dwd_refund_Ex.is_delete IS '逻辑删除标志:0=未删除;1=已逻辑删除。 | 来源: is_delete';
+ COMMENT ON COLUMN dwd_refund_Ex.check_status IS '审核状态。样本全部为 1(已审核/通过)。 | 来源: check_status';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_channel IS '线上支付渠道枚举。样本中全部为 0(线下或默认)。 | 来源: online_pay_channel';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_type IS '在线退款类型。样本全部为 0(原路退回)。 | 来源: online_pay_type';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_terminal IS '退款终端类型。样本全部为 1(前台收银端)。 | 来源: pay_terminal';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_config_id IS '支付配置 ID,例如某个具体支付通道(微信商户号、银联通道等)的配置主键。样本全部为 0。 | 来源: pay_config_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.cashier_point_id IS '收银点编号,例如前台1、前台2、自助机等。样本全部为 0。 | 来源: cashier_point_id';
+ COMMENT ON COLUMN dwd_refund_Ex.operator_id IS '执行退款操作的操作员 ID。样本全部为 0。 | 来源: operator_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_payer_id IS '支付渠道侧的付款人标识,如 openid、银行卡号掩码等。样本全部为空字符串。 | 来源: channel_payer_id';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_pay_no IS '第三方支付平台交易号(如微信支付单号、支付宝交易号等)。当前样本全部为空。 | 来源: channel_pay_no';
+
+-- SCD2 columns for dimension tables (merged from schema_dwd_scd2.sql)
+ALTER TABLE IF EXISTS billiards_dwd.dim_site
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_site_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_table
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_table_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_assistant
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_assistant_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_member
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_member_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_member_card_account
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_member_card_account_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_tenant_goods
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_tenant_goods_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_store_goods
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_store_goods_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_goods_category
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_groupbuy_package
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
+ALTER TABLE IF EXISTS billiards_dwd.dim_groupbuy_package_Ex
+ ADD COLUMN IF NOT EXISTS SCD2_valid_from TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_valid_to TIMESTAMPTZ,
+ ADD COLUMN IF NOT EXISTS SCD2_is_current BOOLEAN;
diff --git a/tmp/schema_dwd_doc.sql b/tmp/schema_dwd_doc.sql
new file mode 100644
index 0000000..b4d2d3d
--- /dev/null
+++ b/tmp/schema_dwd_doc.sql
@@ -0,0 +1,1878 @@
+-- Generated from DWD?????.docx; includes column comments from??
+CREATE SCHEMA IF NOT EXISTS billiards_dwd;
+SET search_path TO billiards_dwd;
+
+-- SCD2 字段统一默认值、中文注释、唯一性(业务键 + 时间段不重叠)控制
+CREATE EXTENSION IF NOT EXISTS btree_gist;
+
+DO $$
+DECLARE
+ rec RECORD;
+BEGIN
+ -- 统一 SCD2 默认值与注释,避免后续手工遗漏
+ FOR rec IN
+ SELECT table_name
+ FROM information_schema.columns
+ WHERE table_schema = 'billiards_dwd'
+ AND column_name = 'scd2_start_time'
+ LOOP
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_start_time SET DEFAULT now()', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_end_time SET DEFAULT ''9999-12-31''', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_is_current SET DEFAULT 1', rec.table_name);
+ EXECUTE format('ALTER TABLE billiards_dwd.%I ALTER COLUMN scd2_version SET DEFAULT 1', rec.table_name);
+
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_start_time IS ''SCD2 开始时间(版本生效起点)''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_end_time IS ''SCD2 结束时间(默认 9999-12-31,表示当前版本仍有效)''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_is_current IS ''SCD2 当前版本标记:1=当前版本,0=历史版本''', rec.table_name);
+ EXECUTE format('COMMENT ON COLUMN billiards_dwd.%I.scd2_version IS ''SCD2 版本号,自增,配合时间段避免重叠''', rec.table_name);
+ END LOOP;
+
+ -- 约束:同一业务键时间段不重叠,且仅有一条当前版本
+ FOR rec IN (
+ SELECT tc.table_name,
+ string_agg(format('%I WITH =', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_eq_expr,
+ string_agg(format('%I', kcu.column_name), ', ' ORDER BY kcu.ordinal_position) AS pk_cols
+ FROM information_schema.table_constraints tc
+ JOIN information_schema.key_column_usage kcu
+ ON tc.table_schema = kcu.table_schema
+ AND tc.table_name = kcu.table_name
+ AND tc.constraint_name = kcu.constraint_name
+ WHERE tc.table_schema = 'billiards_dwd'
+ AND tc.constraint_type = 'PRIMARY KEY'
+ AND EXISTS (
+ SELECT 1 FROM information_schema.columns c
+ WHERE c.table_schema = 'billiards_dwd'
+ AND c.table_name = tc.table_name
+ AND c.column_name = 'scd2_start_time'
+ )
+ GROUP BY tc.table_name
+ )
+ LOOP
+ IF NOT EXISTS (
+ SELECT 1 FROM pg_constraint
+ WHERE conname = format('%s_scd2_no_overlap', rec.table_name)
+ AND conrelid = format('billiards_dwd.%s', rec.table_name)::regclass
+ ) THEN
+ EXECUTE format(
+ 'ALTER TABLE billiards_dwd.%I ADD CONSTRAINT %I EXCLUDE USING gist (%s, tstzrange(scd2_start_time, scd2_end_time) WITH &&) WHERE (scd2_is_current = 1);',
+ rec.table_name,
+ rec.table_name || '_scd2_no_overlap',
+ rec.pk_eq_expr
+ );
+ END IF;
+
+ IF to_regclass(format('billiards_dwd.%s_scd2_current_unique_idx', rec.table_name)) IS NULL THEN
+ EXECUTE format(
+ 'CREATE UNIQUE INDEX %I ON billiards_dwd.%I (%s) WHERE (scd2_is_current = 1);',
+ rec.table_name || '_scd2_current_unique_idx',
+ rec.table_name,
+ rec.pk_cols
+ );
+ END IF;
+ END LOOP;
+END
+$$;
+
+-- SCD2 统一约定(DIM 表使用):
+-- SCD2_start_time TIMESTAMPTZ DEFAULT now() -- 版本开始时间
+-- SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31' -- 版本结束时间
+-- SCD2_is_current INT DEFAULT 1 -- 当前版本标记(1当前/0历史)
+-- SCD2_version INT DEFAULT 1 -- 版本号,自增
+
+-- dim_site
+CREATE TABLE IF NOT EXISTS dim_site (
+ site_id BIGINT,
+ org_id BIGINT,
+ tenant_id BIGINT,
+ shop_name TEXT,
+ site_label TEXT,
+ full_address TEXT,
+ address TEXT,
+ longitude NUMERIC(10,6),
+ latitude NUMERIC(10,6),
+ tenant_site_region_id BIGINT,
+ business_tel TEXT,
+ site_type INTEGER,
+ shop_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site.site_id IS '???? ID?????????????????? site_id ??? | ??: siteProfile.id | ??: ??';
+COMMENT ON COLUMN dim_site.org_id IS '???? ID?????????? | ??: siteProfile.org_id | ??: ??';
+COMMENT ON COLUMN dim_site.tenant_id IS '?? ID????? tenant_id ??? | ??: siteProfile.tenant_id | ??: ??';
+COMMENT ON COLUMN dim_site.shop_name IS '????????? | ??: siteProfile.shop_name';
+COMMENT ON COLUMN dim_site.site_label IS '???????????????? | ??: siteProfile.site_label';
+COMMENT ON COLUMN dim_site.full_address IS '??????? | ??: siteProfile.full_address';
+COMMENT ON COLUMN dim_site.address IS '???????????? | ??: siteProfile.address';
+COMMENT ON COLUMN dim_site.longitude IS '???????? | ??: siteProfile.longitude';
+COMMENT ON COLUMN dim_site.latitude IS '???????? | ??: siteProfile.latitude';
+COMMENT ON COLUMN dim_site.tenant_site_region_id IS '????/?????????? | ??: siteProfile.tenant_site_region_id';
+COMMENT ON COLUMN dim_site.business_tel IS '????? | ??: siteProfile.business_tel';
+COMMENT ON COLUMN dim_site.site_type IS '??????????????????? | ??: siteProfile.site_type';
+COMMENT ON COLUMN dim_site.shop_status IS '??????????????????? | ??: siteProfile.shop_status';
+
+-- dim_site_Ex
+CREATE TABLE IF NOT EXISTS dim_site_Ex (
+ site_id BIGINT,
+ avatar TEXT,
+ address TEXT,
+ longitude NUMERIC(9,6),
+ latitude NUMERIC(9,6),
+ tenant_site_region_id BIGINT,
+ auto_light INTEGER,
+ light_status INTEGER,
+ light_type INTEGER,
+ light_token TEXT,
+ site_type INTEGER,
+ site_label TEXT,
+ attendance_enabled INTEGER,
+ attendance_distance INTEGER,
+ customer_service_qrcode TEXT,
+ customer_service_wechat TEXT,
+ fixed_pay_qrCode TEXT,
+ prod_env TEXT,
+ shop_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (site_id)
+);
+COMMENT ON COLUMN dim_site_Ex.site_id IS '门店主键 ID,唯一标识一家门店。与所有事实表中的 site_id 对应。 | 来源: siteProfile.id | 角色: 主键';
+COMMENT ON COLUMN dim_site_Ex.avatar IS '门店头像 URL。 | 来源: siteProfile.avatar';
+COMMENT ON COLUMN dim_site_Ex.address IS '地址简写。 | 来源: siteProfile.address';
+COMMENT ON COLUMN dim_site_Ex.longitude IS '经度。 | 来源: siteProfile.longitude';
+COMMENT ON COLUMN dim_site_Ex.latitude IS '纬度。 | 来源: siteProfile.latitude';
+COMMENT ON COLUMN dim_site_Ex.tenant_site_region_id IS '地区编码。 | 来源: siteProfile.tenant_site_region_id';
+COMMENT ON COLUMN dim_site_Ex.auto_light IS '是否自动控制灯光:1=是,2=否(根据系统约定)。 | 来源: siteProfile.auto_light';
+COMMENT ON COLUMN dim_site_Ex.light_status IS '灯光状态,系统预留字段。 | 来源: siteProfile.light_status';
+COMMENT ON COLUMN dim_site_Ex.light_type IS '灯光类型,预留字段。 | 来源: siteProfile.light_type';
+COMMENT ON COLUMN dim_site_Ex.light_token IS '灯光控制令牌。 | 来源: siteProfile.light_token';
+COMMENT ON COLUMN dim_site_Ex.site_type IS '门店类型枚举(未在导出中说明,视系统配置)。 | 来源: siteProfile.site_type';
+COMMENT ON COLUMN dim_site_Ex.site_label IS '门店标签,展示用。 | 来源: siteProfile.site_label';
+COMMENT ON COLUMN dim_site_Ex.attendance_enabled IS '门店是否启用考勤功能:1=启用,2=不启用。 | 来源: siteProfile.attendance_enabled';
+COMMENT ON COLUMN dim_site_Ex.attendance_distance IS '考勤打卡距离限制(米)。 | 来源: siteProfile.attendance_distance';
+COMMENT ON COLUMN dim_site_Ex.customer_service_qrcode IS '客服二维码 URL。 | 来源: siteProfile.customer_service_qrcode';
+COMMENT ON COLUMN dim_site_Ex.customer_service_wechat IS '客服微信号。 | 来源: siteProfile.customer_service_wechat';
+COMMENT ON COLUMN dim_site_Ex.fixed_pay_qrCode IS '固定收款二维码。 | 来源: siteProfile.fixed_pay_qrCode';
+COMMENT ON COLUMN dim_site_Ex.prod_env IS '环境标记(生产/测试)。 | 来源: siteProfile.prod_env';
+COMMENT ON COLUMN dim_site_Ex.shop_status IS '门店状态,未在文档解释。 | 来源: siteProfile.shop_status';
+COMMENT ON COLUMN dim_site_Ex.create_time IS '门店创建时间。 | 来源: siteProfile.create_time';
+COMMENT ON COLUMN dim_site_Ex.update_time IS '门店最近更新时间。 | 来源: siteProfile.update_time';
+
+-- dim_table
+CREATE TABLE IF NOT EXISTS dim_table (
+ table_id BIGINT,
+ site_id BIGINT,
+ table_name TEXT,
+ site_table_area_id BIGINT,
+ site_table_area_name TEXT,
+ tenant_table_area_id BIGINT,
+ table_price NUMERIC(18,2),
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table.site_id IS '门店 ID。 | 来源: siteId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_name IS '台桌名称/编号,如 A17、888。 | 来源: tableName';
+COMMENT ON COLUMN dim_table.site_table_area_id IS '门店区 ID,用于区分 A区/B区/补时区等。 | 来源: siteTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.site_table_area_name IS '区域名称,如 “A区”“补时长”。 | 来源: siteTableAreaName';
+COMMENT ON COLUMN dim_table.tenant_table_area_id IS '租户级区域 ID。 | 来源: tenantTableAreaId | 角色: 外键';
+COMMENT ON COLUMN dim_table.table_price IS '台桌基础单价,从table_fee_transactions取值。方法:对应本表id,table_fee_transactions表的site_table_id。';
+
+-- dim_table_Ex
+CREATE TABLE IF NOT EXISTS dim_table_Ex (
+ table_id BIGINT,
+ show_status INTEGER,
+ is_online_reservation INTEGER,
+ table_cloth_use_time INTEGER,
+ table_cloth_use_cycle INTEGER,
+ table_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ DEFAULT now(),
+ SCD2_end_time TIMESTAMPTZ DEFAULT '9999-12-31',
+ SCD2_is_current INT DEFAULT 1,
+ SCD2_version INT DEFAULT 1,
+ PRIMARY KEY (table_id)
+);
+COMMENT ON COLUMN dim_table_Ex.table_id IS '台桌主键,唯一标识一张台或包厢。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_table_Ex.show_status IS '显示状态:1=正常台;其他值=特殊用途(包厢、补时长等)。 | 来源: showStatus';
+COMMENT ON COLUMN dim_table_Ex.is_online_reservation IS '是否可线上预约:1=是,2=否。 | 来源: isOnlineReservation';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_time IS '已使用台呢时长(秒)。 | 来源: tableClothUseTime';
+COMMENT ON COLUMN dim_table_Ex.table_cloth_use_cycle IS '台呢更换周期阈值(秒)。 | 来源: tableClothUseCycle';
+COMMENT ON COLUMN dim_table_Ex.table_status IS '当前台桌状态:1=空闲,2=使用中,3=暂停中,4=锁定。 | 来源: tableStatus';
+
+-- dim_assistant
+CREATE TABLE IF NOT EXISTS dim_assistant (
+ assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_no TEXT,
+ real_name TEXT,
+ nickname TEXT,
+ mobile TEXT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ team_id BIGINT,
+ team_name TEXT,
+ level INTEGER,
+ entry_time TIMESTAMPTZ,
+ resign_time TIMESTAMPTZ,
+ leave_status INTEGER,
+ assistant_status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant.user_id IS '系统用户 ID,用于统一跨模块身份。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.assistant_no IS '助教工号/编号,业务识别用。 | 来源: assistant_no';
+COMMENT ON COLUMN dim_assistant.real_name IS '助教真实姓名。 | 来源: real_name';
+COMMENT ON COLUMN dim_assistant.nickname IS '前台展示昵称。 | 来源: nickname';
+COMMENT ON COLUMN dim_assistant.mobile IS '手机号码。 | 来源: mobile';
+COMMENT ON COLUMN dim_assistant.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.site_id IS '门店 ID。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_id IS '助教团队 ID。 | 来源: team_id | 角色: 外键';
+COMMENT ON COLUMN dim_assistant.team_name IS '团队名称。 | 来源: team_name';
+COMMENT ON COLUMN dim_assistant.level IS '助教等级:8=管理员、10=初级、20=中级、30=高级、40=专家。 | 来源: level';
+COMMENT ON COLUMN dim_assistant.entry_time IS '入职时间。 | 来源: entry_time';
+COMMENT ON COLUMN dim_assistant.resign_time IS '离职时间;远未来日期表示在职。 | 来源: resign_time';
+COMMENT ON COLUMN dim_assistant.leave_status IS '在职状态:0=在职,1=已离职。 | 来源: leave_status';
+COMMENT ON COLUMN dim_assistant.assistant_status IS '账号启用状态:1=启用,2=停用/冻结。 | 来源: assistant_status';
+
+-- dim_assistant_Ex
+CREATE TABLE IF NOT EXISTS dim_assistant_Ex (
+ assistant_id BIGINT,
+ gender INTEGER,
+ birth_date TIMESTAMPTZ,
+ avatar TEXT,
+ introduce TEXT,
+ video_introduction_url TEXT,
+ height NUMERIC(5,2),
+ weight NUMERIC(5,2),
+ shop_name TEXT,
+ group_id BIGINT,
+ group_name TEXT,
+ person_org_id BIGINT,
+ staff_id BIGINT,
+ staff_profile_id BIGINT,
+ assistant_grade DOUBLE PRECISION,
+ sum_grade DOUBLE PRECISION,
+ get_grade_times INTEGER,
+ charge_way INTEGER,
+ allow_cx INTEGER,
+ is_guaranteed INTEGER,
+ salary_grant_enabled INTEGER,
+ entry_type INTEGER,
+ entry_sign_status INTEGER,
+ resign_sign_status INTEGER,
+ work_status INTEGER,
+ show_status INTEGER,
+ show_sort INTEGER,
+ online_status INTEGER,
+ is_delete INTEGER,
+ criticism_status INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_table_id BIGINT,
+ last_table_name TEXT,
+ last_update_name TEXT,
+ order_trade_no BIGINT,
+ ding_talk_synced INTEGER,
+ site_light_cfg_id BIGINT,
+ light_equipment_id TEXT,
+ light_status INTEGER,
+ is_team_leader INTEGER,
+ serial_number BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (assistant_id)
+);
+COMMENT ON COLUMN dim_assistant_Ex.assistant_id IS '助教账号 ID,关联助教服务流水表。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_assistant_Ex.gender IS '性别枚举:0=未填/保密,1=男,2=女。 | 来源: gender';
+COMMENT ON COLUMN dim_assistant_Ex.birth_date IS '出生日期,默认为 0001-01-01 表示未设置。 | 来源: birth_date';
+COMMENT ON COLUMN dim_assistant_Ex.avatar IS '头像 URL。 | 来源: avatar';
+COMMENT ON COLUMN dim_assistant_Ex.introduce IS '个人简介文案(目前为空)。 | 来源: introduce';
+COMMENT ON COLUMN dim_assistant_Ex.video_introduction_url IS '视频介绍 URL。 | 来源: video_introduction_url';
+COMMENT ON COLUMN dim_assistant_Ex.height IS '身高(厘米),0 表示未填。 | 来源: height';
+COMMENT ON COLUMN dim_assistant_Ex.weight IS '体重(公斤),0 表示未填。 | 来源: weight';
+COMMENT ON COLUMN dim_assistant_Ex.shop_name IS '门店名称。 | 来源: shop_name';
+COMMENT ON COLUMN dim_assistant_Ex.group_id IS '上级分组 ID,未使用。 | 来源: group_id';
+COMMENT ON COLUMN dim_assistant_Ex.group_name IS '上级分组名称,空。 | 来源: group_name';
+COMMENT ON COLUMN dim_assistant_Ex.person_org_id IS '人事组织 ID,用于权限和报表分组。 | 来源: person_org_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_id IS '预留员工 ID(全部为0)。 | 来源: staff_id';
+COMMENT ON COLUMN dim_assistant_Ex.staff_profile_id IS '外部人事档案 ID(全部为0)。 | 来源: staff_profile_id';
+COMMENT ON COLUMN dim_assistant_Ex.assistant_grade IS '平均评分(0 表示暂无)。 | 来源: assistant_grade';
+COMMENT ON COLUMN dim_assistant_Ex.sum_grade IS '总评分累加值。 | 来源: sum_grade';
+COMMENT ON COLUMN dim_assistant_Ex.get_grade_times IS '累计评分次数。 | 来源: get_grade_times';
+COMMENT ON COLUMN dim_assistant_Ex.charge_way IS '计费方式:2=计时,其他未出现。 | 来源: charge_way';
+COMMENT ON COLUMN dim_assistant_Ex.allow_cx IS '是否允许促销计费:1=允许。 | 来源: allow_cx';
+COMMENT ON COLUMN dim_assistant_Ex.is_guaranteed IS '是否有保底:1=是。 | 来源: is_guaranteed';
+COMMENT ON COLUMN dim_assistant_Ex.salary_grant_enabled IS '薪资发放开关(值2,具体含义未知)。 | 来源: salary_grant_enabled';
+COMMENT ON COLUMN dim_assistant_Ex.entry_type IS '入职类型:1=正式;其他未出现。 | 来源: entry_type';
+COMMENT ON COLUMN dim_assistant_Ex.entry_sign_status IS '入职签约状态:0=未签约,1=已签约(未出现)。 | 来源: entry_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.resign_sign_status IS '离职签约状态,未出现非 0。 | 来源: resign_sign_status';
+COMMENT ON COLUMN dim_assistant_Ex.work_status IS '工作状态:1=在岗,2=离岗。与 leave_status 呼应。 | 来源: work_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_status IS '前台展示状态:1=显示;其他值未出现。 | 来源: show_status';
+COMMENT ON COLUMN dim_assistant_Ex.show_sort IS '前端排序序号。 | 来源: show_sort';
+COMMENT ON COLUMN dim_assistant_Ex.online_status IS '在线状态:1=在线。 | 来源: online_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_delete IS '逻辑删除标记:0=未删除,1=已删除。 | 来源: is_delete';
+COMMENT ON COLUMN dim_assistant_Ex.criticism_status IS '投诉状态:1=正常,2=有投诉。 | 来源: criticism_status';
+COMMENT ON COLUMN dim_assistant_Ex.create_time IS '账号创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_assistant_Ex.update_time IS '账号最近修改时间。 | 来源: update_time';
+COMMENT ON COLUMN dim_assistant_Ex.start_time IS '配置生效开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_assistant_Ex.end_time IS '配置生效结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_id IS '最近服务的台桌 ID(未必存在)。 | 来源: last_table_id';
+COMMENT ON COLUMN dim_assistant_Ex.last_table_name IS '最近服务球台名称。 | 来源: last_table_name';
+COMMENT ON COLUMN dim_assistant_Ex.last_update_name IS '最近更新该账号的管理员。 | 来源: last_update_name';
+COMMENT ON COLUMN dim_assistant_Ex.order_trade_no IS '最近关联的订单号(非外键,仅做展示)。 | 来源: order_trade_no';
+COMMENT ON COLUMN dim_assistant_Ex.ding_talk_synced IS '是否同步钉钉:1=已同步。 | 来源: ding_talk_synced';
+COMMENT ON COLUMN dim_assistant_Ex.site_light_cfg_id IS '灯控配置 ID(未启用)。 | 来源: site_light_cfg_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_equipment_id IS '灯控设备 ID(未启用)。 | 来源: light_equipment_id';
+COMMENT ON COLUMN dim_assistant_Ex.light_status IS '灯控状态(值2,具体含义未知)。 | 来源: light_status';
+COMMENT ON COLUMN dim_assistant_Ex.is_team_leader IS '是否团队长:0=否,1=是。 | 来源: is_team_leader';
+COMMENT ON COLUMN dim_assistant_Ex.serial_number IS '来源: serial_number';
+
+-- dim_member
+CREATE TABLE IF NOT EXISTS dim_member (
+ member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ mobile TEXT,
+ nickname TEXT,
+ member_card_grade_code BIGINT,
+ member_card_grade_name TEXT,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member.system_member_id IS '跨租户全局会员 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.tenant_id IS '租户 ID。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.register_site_id IS '注册门店 ID。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member.mobile IS '会员手机号。 | 来源: mobile';
+COMMENT ON COLUMN dim_member.nickname IS '昵称(未必是真实姓名)。 | 来源: nickname';
+COMMENT ON COLUMN dim_member.member_card_grade_code IS '会员等级代码:1=金卡?2=银卡?3=钻石卡?4=黑卡?(按照 MD 文档枚举)。 | 来源: member_card_grade_code';
+COMMENT ON COLUMN dim_member.member_card_grade_name IS '等级名称,中文描述。 | 来源: member_card_grade_name';
+COMMENT ON COLUMN dim_member.create_time IS '会员档案创建时间。 | 来源: create_time';
+
+-- dim_member_Ex
+CREATE TABLE IF NOT EXISTS dim_member_Ex (
+ member_id BIGINT,
+ referrer_member_id BIGINT,
+ point NUMERIC(18,2),
+ register_site_name TEXT,
+ growth_value NUMERIC(18,2),
+ user_status INTEGER,
+ status INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_id)
+);
+COMMENT ON COLUMN dim_member_Ex.member_id IS '租户内会员主键。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_Ex.referrer_member_id IS '推荐人会员 ID,营销分析用。 | 来源: referrer_member_id';
+COMMENT ON COLUMN dim_member_Ex.point IS '积分余额(暂未启用)。 | 来源: point';
+COMMENT ON COLUMN dim_member_Ex.register_site_name IS '注册门店名称。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_Ex.growth_value IS '成长值,暂未启用。 | 来源: growth_value';
+COMMENT ON COLUMN dim_member_Ex.user_status IS '会员状态枚举:1=正常,其它值未出现。 | 来源: user_status';
+COMMENT ON COLUMN dim_member_Ex.status IS '帐户状态:1=正常;其它值未出现。 | 来源: status';
+
+-- dim_member_card_account
+CREATE TABLE IF NOT EXISTS dim_member_card_account (
+ member_card_id BIGINT,
+ tenant_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ card_type_id BIGINT,
+ member_card_grade_code BIGINT,
+ member_card_grade_code_name TEXT,
+ member_card_type_name TEXT,
+ member_name TEXT,
+ member_mobile TEXT,
+ balance NUMERIC(18,2),
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ last_consume_time TIMESTAMPTZ,
+ status INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account.tenant_id IS '租户/品牌 ID,用于分隔不同业务主体。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.register_site_id IS '开卡门店 ID,对应 dim_site.site_id。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.tenant_member_id IS '对应会员档案中的 member_id(本租户内)。0 表示未绑定会员。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.system_member_id IS '全局会员 ID,用于跨租户统一会员身份。0 表示未绑定会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.card_type_id IS '卡种 ID,指向卡种配置表。与下面的 grade_code 共同定义卡类别。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code IS '卡等级/卡类代码,区别不同类别卡。2790683528022853=储值卡,2790683528022856=活动抵用券,2790683528022855=台费卡,2790683528022858=酒水卡,2790683528022857=月卡';
+COMMENT ON COLUMN dim_member_card_account.member_card_grade_code_name IS '卡等级中文名称,与 member_card_grade_code 一一对应。 | 来源: member_card_grade_code_name';
+COMMENT ON COLUMN dim_member_card_account.member_card_type_name IS '卡类型名称,通常与 grade_code_name 相同,纯展示字段。 | 来源: member_card_type_name';
+COMMENT ON COLUMN dim_member_card_account.member_name IS '持卡会员姓名快照,部分为空表示未绑定。 | 来源: member_name';
+COMMENT ON COLUMN dim_member_card_account.member_mobile IS '持卡会员手机号快照。 | 来源: member_mobile';
+COMMENT ON COLUMN dim_member_card_account.balance IS '当前余额或额度。对储值卡表示余额,对其他卡表示剩余金额或次数。 | 来源: balance';
+COMMENT ON COLUMN dim_member_card_account.start_time IS '卡片有效期开始时间。 | 来源: start_time';
+COMMENT ON COLUMN dim_member_card_account.end_time IS '卡片有效期结束时间。 | 来源: end_time';
+COMMENT ON COLUMN dim_member_card_account.last_consume_time IS '最近一次消费时间;若为 "1970-01-01" 表示未消费过。 | 来源: last_consume_time';
+COMMENT ON COLUMN dim_member_card_account.status IS '卡状态:1=正常可用;4=过期/停用。其他值在数据中未出现。 | 来源: status';
+COMMENT ON COLUMN dim_member_card_account.is_delete IS '逻辑删除标记:0=未删除;1=已删除。 | 来源: is_delete';
+
+-- dim_member_card_account_Ex
+CREATE TABLE IF NOT EXISTS dim_member_card_account_Ex (
+ member_card_id BIGINT,
+ site_name TEXT,
+ tenant_name VARCHAR(64),
+ tenantAvatar TEXT,
+ effect_site_id BIGINT,
+ able_cross_site INTEGER,
+ card_physics_type INTEGER,
+ card_no TEXT,
+ bind_password TEXT,
+ use_scene TEXT,
+ denomination NUMERIC(18,2),
+ create_time TIMESTAMPTZ,
+ disable_start_time TIMESTAMPTZ,
+ disable_end_time TIMESTAMPTZ,
+ is_allow_give INTEGER,
+ is_allow_order_deduct INTEGER,
+ sort INTEGER,
+ table_discount NUMERIC(10,2),
+ goods_discount NUMERIC(10,2),
+ assistant_discount NUMERIC(10,2),
+ assistant_reward_discount NUMERIC(10,2),
+ table_service_discount NUMERIC(10,2),
+ goods_service_discount NUMERIC(10,2),
+ assistant_service_discount NUMERIC(10,2),
+ coupon_discount NUMERIC(10,2),
+ table_discount_sub_switch INTEGER,
+ goods_discount_sub_switch INTEGER,
+ assistant_discount_sub_switch INTEGER,
+ assistant_reward_discount_sub_switch INTEGER,
+ goods_discount_range_type INTEGER,
+ table_deduct_radio NUMERIC(10,2),
+ goods_deduct_radio NUMERIC(10,2),
+ assistant_deduct_radio NUMERIC(10,2),
+ table_service_deduct_radio NUMERIC(10,2),
+ goods_service_deduct_radio NUMERIC(10,2),
+ assistant_service_deduct_radio NUMERIC(10,2),
+ assistant_reward_deduct_radio NUMERIC(10,2),
+ coupon_deduct_radio NUMERIC(10,2),
+ cardSettleDeduct NUMERIC(18,2),
+ tableCardDeduct NUMERIC(18,2),
+ tableServiceCardDeduct NUMERIC(18,2),
+ goodsCarDeduct NUMERIC(18,2),
+ goodsServiceCardDeduct NUMERIC(18,2),
+ assistantCardDeduct NUMERIC(18,2),
+ assistantServiceCardDeduct NUMERIC(18,2),
+ assistantRewardCardDeduct NUMERIC(18,2),
+ couponCardDeduct NUMERIC(18,2),
+ deliveryFeeDeduct NUMERIC(18,2),
+ tableAreaId TEXT,
+ goodsCategoryId TEXT,
+ pdAssisnatLevel TEXT,
+ cxAssisnatLevel TEXT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (member_card_id)
+);
+COMMENT ON COLUMN dim_member_card_account_Ex.member_card_id IS '会员卡账户主键,唯一标识一张具体卡。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_member_card_account_Ex.site_name IS '门店名称展示字段(全部相同)。 | 来源: site_name';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenant_name IS '租户名称(当前导出为空)。 | 来源: tenantName';
+COMMENT ON COLUMN dim_member_card_account_Ex.tenantAvatar IS '租户头像 URL(当前导出为空)。 | 来源: tenantAvatar';
+COMMENT ON COLUMN dim_member_card_account_Ex.effect_site_id IS '卡片限定生效门店 ID。0 表示不限门店,配合 able_cross_site=1 表示全店通用。 | 来源: effect_site_id';
+COMMENT ON COLUMN dim_member_card_account_Ex.able_cross_site IS '是否允许跨门店使用该卡:1=允许跨店;0=仅限开卡门店。 | 来源: able_cross_site';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_physics_type IS '物理卡类型:1=实体/标准卡;其他值未出现,含义未知。 | 来源: card_physics_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.card_no IS '物理卡号或条码(当前全部为空)。 | 来源: card_no';
+COMMENT ON COLUMN dim_member_card_account_Ex.bind_password IS '卡绑定密码(未启用)。 | 来源: bind_password';
+COMMENT ON COLUMN dim_member_card_account_Ex.use_scene IS '使用场景说明(当前为空)。 | 来源: use_scene';
+COMMENT ON COLUMN dim_member_card_account_Ex.denomination IS '面额或初始储值额度(当前均为 0.0,未启用)。 | 来源: denomination';
+COMMENT ON COLUMN dim_member_card_account_Ex.create_time IS '卡片创建时间。 | 来源: create_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_start_time IS '卡片禁用开始时间,当前为默认值表示未禁用。 | 来源: disable_start_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.disable_end_time IS '卡片禁用结束时间,当前为默认值表示未禁用。 | 来源: disable_end_time';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_give IS '是否允许转赠给他人:0=不允许;1=允许。 | 来源: is_allow_give';
+COMMENT ON COLUMN dim_member_card_account_Ex.is_allow_order_deduct IS '是否允许在订单层面统一扣款:0=不允许;1=允许。 | 来源: is_allow_order_deduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.sort IS '前端排序序号。 | 来源: sort';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount IS '台费折扣率(折扣百分比,10.0=不打折,9.0=九折等)。当前全部 10.0。 | 来源: table_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount IS '商品折扣率,当前为 10.0 表示无折扣。 | 来源: goods_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount IS '助教服务折扣率,当前为 10.0。 | 来源: assistant_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount IS '助教奖励折扣率,当前为 10.0(未启用)。 | 来源: assistant_reward_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_discount IS '台费服务类折扣率,当前为 10.0。 | 来源: table_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_discount IS '商品服务折扣率,当前为 10.0。 | 来源: goods_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_discount IS '助教服务类折扣率,当前为 10.0。 | 来源: assistant_service_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_discount IS '使用券的折扣比例(全部 10.0,未使用)。 | 来源: coupon_discount';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_discount_sub_switch IS '台费折扣叠加开关:1=叠加其他折扣;2=不叠加,仅用卡折扣。 | 来源: table_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_sub_switch IS '商品折扣叠加开关,意义同上。 | 来源: goods_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_discount_sub_switch IS '助教折扣叠加开关,意义同上。 | 来源: assistant_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_discount_sub_switch IS '助教奖励折扣叠加开关(未启用)。 | 来源: assistant_reward_discount_sub_switch';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_discount_range_type IS '商品折扣范围类型,未在文档说明具体含义。 | 来源: goods_discount_range_type';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_deduct_radio IS '台费抵扣比例(百分比)。100.0 表示允许全额抵扣;0=不允许。 | 来源: table_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_deduct_radio IS '商品抵扣比例,意义同上。 | 来源: goods_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_deduct_radio IS '助教抵扣比例,意义同上。 | 来源: assistant_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.table_service_deduct_radio IS '台费服务金抵扣比例。 | 来源: table_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.goods_service_deduct_radio IS '商品服务金抵扣比例。 | 来源: goods_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_service_deduct_radio IS '助教服务金抵扣比例。 | 来源: assistant_service_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistant_reward_deduct_radio IS '助教奖励金抵扣比例(未启用)。 | 来源: assistant_reward_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.coupon_deduct_radio IS '券抵扣比例(未启用)。 | 来源: coupon_deduct_radio';
+COMMENT ON COLUMN dim_member_card_account_Ex.cardSettleDeduct IS '结算时统一扣卡金额配置(当前为 0.0,未使用)。 | 来源: cardSettleDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableCardDeduct IS '台费扣卡金额配置,当前 0.0。 | 来源: tableCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableServiceCardDeduct IS '台费服务金扣卡金额配置。 | 来源: tableServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCarDeduct IS '商品扣卡金额配置。 | 来源: goodsCarDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsServiceCardDeduct IS '商品服务金扣卡金额配置。 | 来源: goodsServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantCardDeduct IS '助教扣卡金额配置。 | 来源: assistantCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantServiceCardDeduct IS '助教服务金扣卡金额配置。 | 来源: assistantServiceCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.assistantRewardCardDeduct IS '助教奖励金扣卡金额配置(未启用)。 | 来源: assistantRewardCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.couponCardDeduct IS '使用券扣卡金额配置。 | 来源: couponCardDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.deliveryFeeDeduct IS '配送费扣卡金额配置(未启用)。 | 来源: deliveryFeeDeduct';
+COMMENT ON COLUMN dim_member_card_account_Ex.tableAreaId IS '可用台区 ID 列表,空表示不限台区。 | 来源: tableAreaId';
+COMMENT ON COLUMN dim_member_card_account_Ex.goodsCategoryId IS '可用商品分类 ID 列表,空表示不限制商品类别。 | 来源: goodsCategoryId';
+COMMENT ON COLUMN dim_member_card_account_Ex.pdAssisnatLevel IS '允许的陪打助教等级列表,空表示不限。 | 来源: pdAssisnatLevel';
+COMMENT ON COLUMN dim_member_card_account_Ex.cxAssisnatLevel IS '允许的促销助教等级列表,空表示不限。 | 来源: cxAssisnatLevel';
+
+-- dim_tenant_goods
+CREATE TABLE IF NOT EXISTS dim_tenant_goods (
+ tenant_goods_id BIGINT,
+ tenant_id BIGINT,
+ supplier_id BIGINT,
+ category_name VARCHAR(64),
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ goods_name VARCHAR(128),
+ goods_number VARCHAR(64),
+ unit VARCHAR(16),
+ market_price NUMERIC(18,2),
+ goods_state INTEGER,
+ create_time TIMESTAMPTZ,
+ update_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods.tenant_id IS '租户/品牌 ID,用于区分不同商户。当前样本中全表同一值,但模型上应作为维表外键,用于关联租户维度。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.supplier_id IS '供应商 ID,用于关联供应商档案维度。当前样本全部为 0,说明门店尚未维护供应商信息或导出视图未包含真实供应商关联,但字段含义明确。 | 来源: supplier_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.category_name IS '商品一级分类名称(可读名称),例如:零食、饮料、香烟、雪糕、小吃、酒水、面、槟榔等。真实分类关联通过 goods_category_id 与 goods_second_category_id 实现,此字段主要用于展示和直观分析。 | 来源: categoryName';
+COMMENT ON COLUMN dim_tenant_goods.goods_category_id IS '商品一级分类 ID。与分类维表(例如 dim_goods_category)关联,构成商品分类的第一层。一个 goods_category_id 对应一个 category_name。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_second_category_id IS '商品二级分类 ID。与分类维表的二级节点关联,用于更细粒度的品类统计。取值数目约十四种,每个值属于某个一级分类之下。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_tenant_goods.goods_name IS '商品名称(前台展示名),如 “东方树叶”“红烧牛肉面”“百威 235 毫升”等。当前样本中基本唯一。作为用户认知的主显示名称,用于报表、前台展示、小票打印。 | 来源: goods_name';
+COMMENT ON COLUMN dim_tenant_goods.goods_number IS '商品内部编号或自定义货号。当前样本中各记录不重复,如 “1”“2”“10”“11” 等。可用于与其他系统对接或人工查找,有一定对账和排错价值。 | 来源: goods_number';
+COMMENT ON COLUMN dim_tenant_goods.unit IS '商品计量单位,例如:瓶、包、个、份、根、盒、杯、桶、盘、支等。用于解释数量含义,是销售数量与库存数量的度量单位。 | 来源: unit';
+COMMENT ON COLUMN dim_tenant_goods.market_price IS '商品标价或标准销售单价。例如 2、5、6、8、10、12、15、18、20、28 元。POS 默认销售价格,结算时的基础金额字段。 | 来源: market_price';
+COMMENT ON COLUMN dim_tenant_goods.goods_state IS '商品状态枚举。当前样本全部为 1,推测含义为“正常”“已上架”或“有效”。其他值(数据中未出现)通常表示下架、停用或草稿状态。用于控制商品是否可销售。 | 来源: goods_state';
+COMMENT ON COLUMN dim_tenant_goods.create_time IS '商品档案创建时间,格式为 “YYYY-MM-DD HH:MM:SS”。每条记录唯一。用于增量抽取和审计,也可用于分析商品生命周期。 | 来源: create_time';
+COMMENT ON COLUMN dim_tenant_goods.update_time IS '商品档案最近一次修改时间,可为空(表示自创建后未修改)。用于增量同步、变化跟踪和审计分析。 | 来源: update_time';
+COMMENT ON COLUMN dim_tenant_goods.is_delete IS '逻辑删除标志。枚举:0 表示未删除(有效商品);1 表示已逻辑删除(在前台不再展示)。当前样本全部为 0。用于软删除控制和历史数据保留。 | 来源: is_delete';
+
+-- dim_tenant_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_tenant_goods_Ex (
+ tenant_goods_id BIGINT,
+ remark_name VARCHAR(128),
+ pinyin_initial VARCHAR(128),
+ goods_cover VARCHAR(512),
+ goods_bar_code VARCHAR(64),
+ commodity_code VARCHAR(64),
+ commodity_code_list VARCHAR(256),
+ min_discount_price NUMERIC(18,2),
+ cost_price NUMERIC(18,2),
+ cost_price_type INTEGER,
+ able_discount INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ is_in_site BOOLEAN,
+ able_site_transfer INTEGER,
+ common_sale_royalty INTEGER,
+ point_sale_royalty INTEGER,
+ out_goods_id BIGINT,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (tenant_goods_id)
+);
+COMMENT ON COLUMN dim_tenant_goods_Ex.tenant_goods_id IS '租户级商品档案主键 ID,唯一标识一条商品档案。所有业务事实表(销售、库存等)中引用租户级商品时应指向此字段。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_tenant_goods_Ex.remark_name IS '商品备注名或别名,目前样本中均为空。设计用途为简写名、特殊展示名或内部备注,在当前门店尚未启用。 | 来源: remark_name';
+COMMENT ON COLUMN dim_tenant_goods_Ex.pinyin_initial IS '商品拼音首字母或助记码,用于前台按拼音检索,如 “DFSY,DFSX”“HSNRM,GSNRM”“SP” 等。主要为操作便利,对经营分析影响较小。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_cover IS '商品封面图片 URL,用于前端展示商品图片。多个商品可能共用同一图片。对经营和结算逻辑无直接影响。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_tenant_goods_Ex.goods_bar_code IS '商品条码(如 EAN 码)。当前样本全部为空。含义明确但尚未使用,未来可用于扫码收银或与第三方商品库对接。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code IS '对外商品编码或系列编码,用于与外部系统或其他内部模块对接。例如 “10000”“100000”“10000028”等。一个编码在多条商品上复用,说明它不是主键而是“系列标识”或“外部编码”。具体业务含义依赖上游系统定义。 | 来源: commodity_code';
+COMMENT ON COLUMN dim_tenant_goods_Ex.commodity_code_list IS '商品编码列表的序列化形式,对应源 JSON 的数组字段(当前每条记录仅一个元素)。设计上支持 “一个商品多个编码” 场景,目前仅为 commodity_code 的冗余表现形式。 | 来源: commodityCode';
+COMMENT ON COLUMN dim_tenant_goods_Ex.min_discount_price IS '商品可售最低价(底价)。部分记录为 0.00,表示未设置底价或沿用系统默认规则。用于限制打折或手动改价的下限,防止亏损销售。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price IS '商品成本价,当前大多数为 0.00,仅少数录入 2.0、2.5、3.0 等。用于成本核算与毛利分析。虽当前门店未完整维护,但字段含义清晰,属于成本分析必备结构。 | 来源: cost_price';
+COMMENT ON COLUMN dim_tenant_goods_Ex.cost_price_type IS '成本价格类型枚举,用于标识成本价的来源或计算方式。已知取值:1 和 2。常见推测:1 表示手工录入成本;2 表示按最近进货价或加权平均价生成。具体含义需结合系统枚举字典确认。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_discount IS '是否允许该商品参与折扣的标志。已知取值:1。按命名推断枚举约定为:1 表示允许参与打折;0 表示不允许参与打折(当前样本未出现)。配合活动、整单折扣等控制哪些商品可享优惠。 | 来源: able_discount';
+COMMENT ON COLUMN dim_tenant_goods_Ex.sale_channel IS '销售渠道类型枚举。当前样本全部为 1,推测为“线下门店正常销售渠道”。理论上可扩展为不同渠道值,例如外卖、小程序、电商等,用于渠道维度分析。具体枚举说明依赖系统配置。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_warehousing IS '是否纳入库存管理的标志。已知取值:1,表示纳入库存管理;0 则表示不纳入库存管理(虚拟商品等,当前未出现)。本门店所有商品均启用库存管理。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_tenant_goods_Ex.is_in_site IS '是否在当前门店启用或上架。当前样本全部为 false。由于该文件是租户级商品档案视图,且 isInSite 全为 false,该字段在本视图的实际含义存在不确定性,可能仅在门店级商品表中才有明确业务意义。 | 来源: isInSite';
+COMMENT ON COLUMN dim_tenant_goods_Ex.able_site_transfer IS '是否允许门店间调拨或门店级操作的枚举。已知取值:2 为绝大多数,0 为少数一条。按命名推测大致含义为:2 表示允许调拨或默认允许;0 表示禁止调拨。实际枚举定义需查阅系统配置,当前无法完全确定具体业务规则。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_tenant_goods_Ex.common_sale_royalty IS '普通销售提成或佣金配置字段,单位和含义需结合上游系统(可能为金额或比例)。当前样本全部为 0,说明未启用商品级提成配置。 | 来源: common_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.point_sale_royalty IS '积分销售相关的提成或赠送规则配置字段。当前样本全部为 0,同样未启用该功能。具体数值含义(百分比或固定值)需结合系统定义。 | 来源: point_sale_royalty';
+COMMENT ON COLUMN dim_tenant_goods_Ex.out_goods_id IS '外部系统商品 ID,用于对接第三方平台或统一商品库时作为映射主键。目前样本全部为 0,说明尚未配置外部商品映射,具体对接规则依赖上游系统。 | 来源: out_goods_id';
+
+-- dim_store_goods
+CREATE TABLE IF NOT EXISTS dim_store_goods (
+ site_goods_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ tenant_goods_id BIGINT,
+ goods_name TEXT,
+ goods_category_id BIGINT,
+ goods_second_category_id BIGINT,
+ category_level1_name TEXT,
+ category_level2_name TEXT,
+ batch_stock_qty INTEGER,
+ sale_qty INTEGER,
+ total_sales_qty INTEGER,
+ sale_price NUMERIC(18,2),
+ created_at TIMESTAMPTZ,
+ updated_at TIMESTAMPTZ,
+ avg_monthly_sales NUMERIC(18,4),
+ goods_state INTEGER,
+ enable_status INTEGER,
+ send_state INTEGER,
+ is_delete INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods.tenant_id IS '租户/品牌 ID,同一品牌下多个门店共享,用于跨门店汇总分析。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.site_id IS '门店 ID,对应门店维度表主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.tenant_goods_id IS '租户级(品牌级)商品 ID,用于关联 dim_tenant_goods,实现跨门店统一商品档案。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_name IS '商品名称,例如“合味道泡面”“地道肠”“茶位费”。 | 来源: goods_name';
+COMMENT ON COLUMN dim_store_goods.goods_category_id IS '商品一级分类 ID,对应商品分类维表主键,与 category_level1_name 一一对应。 | 来源: goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.goods_second_category_id IS '商品二级分类 ID,其父分类为 goods_category_id。 | 来源: goods_second_category_id | 角色: 外键';
+COMMENT ON COLUMN dim_store_goods.category_level1_name IS '一级分类名称,如“零食”“酒水”“服务费”,用于报表维度展示。 | 来源: oneCategoryName';
+COMMENT ON COLUMN dim_store_goods.category_level2_name IS '二级分类名称,如“面”“洋酒”“纸巾”,用于更细粒度分类分析。 | 来源: twoCategoryName';
+COMMENT ON COLUMN dim_store_goods.batch_stock_qty IS '当前成本批次的库存数量,用于按 cost_price 估算库存价值。 | 来源: batch_stock_quantity';
+COMMENT ON COLUMN dim_store_goods.sale_qty IS '截至导出时的销售数量(件),当前数据中与 total_sales_qty 相同。 | 来源: sale_num';
+COMMENT ON COLUMN dim_store_goods.total_sales_qty IS '累计销售数量;当前导出周期下与 sale_qty 一致,为历史全量口径。 | 来源: total_sales';
+COMMENT ON COLUMN dim_store_goods.sale_price IS '商品标准销售价(挂牌价),单位为元。实际结算可能有折扣或券抵扣。 | 来源: sale_price';
+COMMENT ON COLUMN dim_store_goods.created_at IS '门店商品档案创建时间(在门店建立该商品档案时的时间点)。 | 来源: create_time';
+COMMENT ON COLUMN dim_store_goods.updated_at IS '最近一次修改商品档案的时间(包括价格调整、状态变更等)。 | 来源: update_time';
+COMMENT ON COLUMN dim_store_goods.avg_monthly_sales IS '平均月销量(件/月),由某个统计周期内销售数据折算而来,用于补货和品类管理分析。 | 来源: average_monthly_sales';
+COMMENT ON COLUMN dim_store_goods.goods_state IS '商品基础状态枚举:1=正常状态(主流值),2=特殊状态(如新建未完全启用或停售但未彻底下架,通常伴随 stock=0、days_on_shelf=0)。 | 来源: goods_state';
+COMMENT ON COLUMN dim_store_goods.enable_status IS '档案启用状态:1=启用;2=停用(推测,样本中未出现);控制商品档案是否参与业务处理。 | 来源: enable_status';
+COMMENT ON COLUMN dim_store_goods.send_state IS '销售端可售状态:1=可销售/可下单;其他值可能代表停售或仅内部使用(当前样本全部为 1)。 | 来源: send_state';
+COMMENT ON COLUMN dim_store_goods.is_delete IS '逻辑删除标志:0=未删除(有效档案);1=已删除(逻辑删除,不再参与业务但保留历史引用)。 | 来源: is_delete';
+
+-- dim_store_goods_Ex
+CREATE TABLE IF NOT EXISTS dim_store_goods_Ex (
+ site_goods_id BIGINT,
+ site_name TEXT,
+ unit TEXT,
+ goods_barcode TEXT,
+ goods_cover_url TEXT,
+ pinyin_initial TEXT,
+ stock_qty INTEGER,
+ stock_secondary_qty INTEGER,
+ safety_stock_qty INTEGER,
+ cost_price NUMERIC(18,4),
+ cost_price_type INTEGER,
+ provisional_total_cost NUMERIC(18,2),
+ total_purchase_cost NUMERIC(18,2),
+ min_discount_price NUMERIC(18,2),
+ is_discountable INTEGER,
+ days_on_shelf INTEGER,
+ audit_status INTEGER,
+ sale_channel INTEGER,
+ is_warehousing INTEGER,
+ freeze_status INTEGER,
+ forbid_sell_status INTEGER,
+ able_site_transfer INTEGER,
+ custom_label_type INTEGER,
+ option_required INTEGER,
+ remark TEXT,
+ sort_order INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (site_goods_id)
+);
+COMMENT ON COLUMN dim_store_goods_Ex.site_goods_id IS '门店级商品 ID,本表主键;其它业务表中的 site_goods_id 与此对应,用于库存、销售等关联。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_store_goods_Ex.site_name IS '门店名称,例如“朗朗桌球”,是对 site_id 的冗余展示,方便直接阅读。 | 来源: siteName';
+COMMENT ON COLUMN dim_store_goods_Ex.unit IS '销售计量单位,如“包”“瓶”“个”“份”“杯”等。 | 来源: unit';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_barcode IS '商品条形码,用于扫码销售;当前样本多为空。 | 来源: goods_bar_code';
+COMMENT ON COLUMN dim_store_goods_Ex.goods_cover_url IS '商品图片 URL,用于前端展示商品图片。 | 来源: goods_cover';
+COMMENT ON COLUMN dim_store_goods_Ex.pinyin_initial IS '商品名称拼音首字母缩写,有时多个别名用逗号分隔,用于按字母快速检索和排序。 | 来源: pinyin_initial';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_qty IS '当前主单位可用库存数量,以 unit 为单位。 | 来源: stock';
+COMMENT ON COLUMN dim_store_goods_Ex.stock_secondary_qty IS '副单位库存数量;若商品存在双单位(如箱/瓶),用于记录副单位库存;当前门店未启用双单位库存,样本中为 0。 | 来源: stock_A';
+COMMENT ON COLUMN dim_store_goods_Ex.safety_stock_qty IS '安全库存阈值,低于该值时系统可提示补货;当前门店尚未配置,样本中为 0。 | 来源: safe_stock';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price IS '商品单件成本价,单位元;部分商品为 0,表示未录入或由其它模块结转成本。 | 来源: cost_price';
+COMMENT ON COLUMN dim_store_goods_Ex.cost_price_type IS '成本类型枚举:1=固定成本价(按 cost_price 计),2=动态成本价(按采购单等方式结转,当前多数仍为暂估)。 | 来源: cost_price_type';
+COMMENT ON COLUMN dim_store_goods_Ex.provisional_total_cost IS '当前库存暂估总成本,单位元;通常约等于 batch_stock_qty × cost_price。 | 来源: provisional_total_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.total_purchase_cost IS '当前库存总采购成本,单位元;当前样本中与 provisional_total_cost 相等,为后续精算成本预留。 | 来源: total_purchase_cost';
+COMMENT ON COLUMN dim_store_goods_Ex.min_discount_price IS '最低允许成交价(限价),单位元;收银改价时需保证成交价 ≥ 此值,为 0 时表示未设置限价或由其它规则控制。 | 来源: min_discount_price';
+COMMENT ON COLUMN dim_store_goods_Ex.is_discountable IS '是否允许参与折扣的标志:1=允许参与折扣;0=不参与任何折扣策略。当前样本全部为 1。 | 来源: able_discount';
+COMMENT ON COLUMN dim_store_goods_Ex.days_on_shelf IS '商品在架天数或可售天数,大致等于当前时间减去首次上架时间;0 通常表示刚建档或刚启用。 | 来源: days_available';
+COMMENT ON COLUMN dim_store_goods_Ex.audit_status IS '审核状态枚举:2=审核通过(当前唯一值);其他值可能代表待提交、待审核、审核不通过等。 | 来源: audit_status';
+COMMENT ON COLUMN dim_store_goods_Ex.sale_channel IS '销售渠道枚举:当前样本全部为 1 表示线下门店渠道;其他值可用于区分外卖、线上商城等渠道。 | 来源: sale_channel';
+COMMENT ON COLUMN dim_store_goods_Ex.is_warehousing IS '是否纳入库存管理:1=参与库存管理(有出入库流水);0 或其他值可能表示不计库存(样本中全部为 1)。 | 来源: is_warehousing';
+COMMENT ON COLUMN dim_store_goods_Ex.freeze_status IS '冻结状态:0=未冻结;非 0 可能表示锁定库存或禁止出库,具体业务规则需系统确认。 | 来源: freeze';
+COMMENT ON COLUMN dim_store_goods_Ex.forbid_sell_status IS '禁止销售状态:1=未禁止,允许销售;2=被禁止销售,即使上架也不能卖(含义基于命名和行业惯例推测)。 | 来源: forbid_sell_status';
+COMMENT ON COLUMN dim_store_goods_Ex.able_site_transfer IS '是否允许跨门店调拨或跨站点共享库存:2=不允许跨店调拨(当前主流值);0=未配置(个别记录),含义为是否参与跨店调拨功能。 | 来源: able_site_transfer';
+COMMENT ON COLUMN dim_store_goods_Ex.custom_label_type IS '自定义标签类型(基于字段名和取值推测):2=使用自定义标签;1 可能表示使用系统默认标签。具体影响哪些标签功能需业务确认。 | 来源: custom_label_type';
+COMMENT ON COLUMN dim_store_goods_Ex.option_required IS '是否需要额外选项或规格(基于字段名和取值推测):1=不需要额外选项,按单规格销售;其他值可能表示必须选择配料或口味。当前样本全部为 1。 | 来源: option_required';
+COMMENT ON COLUMN dim_store_goods_Ex.remark IS '商品备注,可填写口味说明、供应商信息、注意事项等;当前样本全部为空。 | 来源: remark';
+COMMENT ON COLUMN dim_store_goods_Ex.sort_order IS '前端展示排序权重,控制商品在列表中的显示顺序,具体规则(数值越大还是越小排前)由业务配置决定。 | 来源: sort';
+
+-- dim_goods_category
+CREATE TABLE IF NOT EXISTS dim_goods_category (
+ category_id BIGINT,
+ tenant_id BIGINT,
+ category_name VARCHAR(50),
+ alias_name VARCHAR(50),
+ parent_category_id BIGINT,
+ business_name VARCHAR(50),
+ tenant_goods_business_id BIGINT,
+ category_level INTEGER,
+ is_leaf INTEGER,
+ open_salesman INTEGER,
+ sort_order INTEGER,
+ is_warehousing INTEGER,
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (category_id)
+);
+COMMENT ON COLUMN dim_goods_category.category_id IS '分类节点主键。来自分类树节点的 id,在整个商品分类维度内唯一。用于在事实表中作为商品分类外键引用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_goods_category.tenant_id IS '租户 ID(商户/品牌 ID)。当前所有节点取值相同,表示同一个租户下的分类树。事实表可通过该字段与租户维度或门店维度间接关联。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_name IS '分类名称。一级大类示例:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。二级子类示例:槟榔、皮头、球杆、其他、饮料、酒水、茶水、咖啡、加料、洋酒、果盘、面、小吃等。用于前台展示和报表按细分类统计。 | 来源: category_name';
+COMMENT ON COLUMN dim_goods_category.alias_name IS '分类别名。当前样例数据全部为空字符串,预留给业务方做简称或别名展示。对现阶段经营分析无影响。 | 来源: alias_name';
+COMMENT ON COLUMN dim_goods_category.parent_category_id IS '父级分类 ID。根节点取值为 0,表示没有父分类;子节点取值为父分类的 id。与 category_id 共同形成树形层级关系。 | 来源: pid | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.business_name IS '业务大类名称。将多个细分类归入同一业务线。观测值与一级大类相同:槟榔、器材、酒水、水果、零食、雪糕、香烟、其他、小吃。子类的 business_name 继承所属根节点的大类名称。用于按业务线汇总库存和销售。 | 来源: business_name';
+COMMENT ON COLUMN dim_goods_category.tenant_goods_business_id IS '业务大类 ID。每个 business_name 对应唯一一个 tenant_goods_business_id,根节点和其下所有子节点共享同一取值。例如“酒水”大类及其子类饮料、茶水、咖啡、加料、洋酒拥有相同的业务 ID。可作为外键连接“业务线维度表”。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dim_goods_category.category_level IS '分类层级:1 表示一级大类(pid = 0),2 表示二级子类(pid ≠ 0)。方便在报表中区分大类与子类进行分组和展示层级控制。 | 来源: 由 pid 推导';
+COMMENT ON COLUMN dim_goods_category.is_leaf IS '是否叶子节点:1 表示叶子分类(categoryBoxes 为空列表),0 表示非叶子分类(存在子分类)。当前样例数据中,一级大类是非叶子节点,二级分类是叶子节点。用于树状导航或限制只能在叶子分类建商品。 | 来源: 由 categoryBoxes 推导';
+COMMENT ON COLUMN dim_goods_category.open_salesman IS '营业员开关控制。枚举含义根据业务系统定义,一般设计为:1 表示启用营业员/导购相关功能,2 表示关闭或不启用。当前样例所有分类取值为 2,说明这一套分类在库存模块中统一未启用营业员逻辑。对目前的经营分析影响较小。 | 来源: open_salesman';
+COMMENT ON COLUMN dim_goods_category.sort_order IS '分类排序序号。来自 sort 字段,用于前端展示顺序控制,数值越小越靠前。当前大部分分类为 0,仅少数为 1,说明排序配置较为粗略。对指标统计无实质影响。 | 来源: sort';
+COMMENT ON COLUMN dim_goods_category.is_warehousing IS '是否参与库存管理。枚举:1 表示参与库存管理,0 表示不参与(如服务类商品、手工费用)。当前文件中所有分类取值为 1,表示这一份分类树只包含“走库存”的商品分类。可在库存报表中用作过滤条件。 | 来源: is_warehousing';
+
+-- dim_groupbuy_package
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package (
+ groupbuy_package_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ package_name VARCHAR(200),
+ package_template_id BIGINT,
+ selling_price NUMERIC(10,2),
+ coupon_face_value NUMERIC(10,2),
+ duration_seconds INTEGER,
+ start_time TIMESTAMPTZ,
+ end_time TIMESTAMPTZ,
+ table_area_name VARCHAR(100),
+ is_enabled INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ tenant_table_area_id_list VARCHAR(512),
+ card_type_ids VARCHAR(255),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_id IS '租户(品牌/商户)ID。本数据集中全表相同,表示同一品牌。 | 来源: tenant_id | 角色: 外键(指向租户维)';
+COMMENT ON COLUMN dim_groupbuy_package.site_id IS '门店 ID,本表所有记录属于同一门店。与其他 JSON 的 site_id 一致。 | 来源: site_id | 角色: 外键(指向门店维)';
+COMMENT ON COLUMN dim_groupbuy_package.package_name IS '团购套餐名称,用于前台展示及核销界面,例如“早场特惠一小时”“KTV欢唱四小时”等。 | 来源: package_name';
+COMMENT ON COLUMN dim_groupbuy_package.package_template_id IS '上层套餐 ID 或总部/系统级套餐 ID。多个 groupbuy_package_id 可能共享同一个 package_template_id,表示同一业务套餐在不同门店或不同版本下的配置。 | 来源: package_id | 角色: 外键(指向套餐模板维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.selling_price IS '团购售卖价,面向顾客在外部平台的成交价格。当前样本全部为 0,实际平台售价可能在外部系统,不在本地落地。 | 来源: selling_price';
+COMMENT ON COLUMN dim_groupbuy_package.coupon_face_value IS '券面值或内部结算面值。表示此套餐在门店侧可以抵扣的金额,用于验券或套餐流水时记账。例如“早场特惠一小时”可配置为 40.00,“KTV欢唱四小时”可配置为 200.00。当前样本为 0 但字段设计上非常关键。 | 来源: coupon_money';
+COMMENT ON COLUMN dim_groupbuy_package.duration_seconds IS '套餐包含的时长,单位为秒。常见取值:3600 表示 1 小时,7200 表示 2 小时,14400 表示 4 小时。核销时可用于换算可用台费时长。 | 来源: duration';
+COMMENT ON COLUMN dim_groupbuy_package.start_time IS '套餐整体生效开始时间。例如“2025-07-20 00:00:00”。通常从某日零点开始。 | 来源: start_time';
+COMMENT ON COLUMN dim_groupbuy_package.end_time IS '套餐整体生效结束时间。在该时间点之后不可使用。极大日期(如 9999-12-31 23:59:59)可视为长期有效。 | 来源: end_time';
+COMMENT ON COLUMN dim_groupbuy_package.table_area_name IS '套餐适用的门店台区名称,例如“A区中八”“B区中八”“斯诺克”“包厢”“KTV”等。主要用于展示和过滤,配合区域 ID 列实现人类可读的说明。 | 来源: table_area_name';
+COMMENT ON COLUMN dim_groupbuy_package.is_enabled IS '启用状态枚举。1 表示启用或上架;2 表示停用或下架。侧重表示“配置是否上架”,与 effective_status 区分。 | 来源: is_enabled';
+COMMENT ON COLUMN dim_groupbuy_package.is_delete IS '逻辑删除标志。0 表示正常;1 表示逻辑删除(数据仍保留但不再使用)。当前样本全部为 0。 | 来源: is_delete';
+COMMENT ON COLUMN dim_groupbuy_package.create_time IS '套餐配置在系统中的创建时间,用于审计和版本追踪。 | 来源: create_time';
+COMMENT ON COLUMN dim_groupbuy_package.tenant_table_area_id_list IS '租户级台区分组 ID 列表。当前每条记录为一个大整数(例如 2791960001957765)字符串,表示“台区分组”主键。系统通过此分组再关联到具体多个台区。 | 来源: tenant_table_area_id_list | 角色: 外键(指向台区分组维,后续可建)';
+COMMENT ON COLUMN dim_groupbuy_package.card_type_ids IS '允许使用本套餐的会员卡类型 ID 列表。当前样本统一为字符串“0”,表示未限制卡种,任意顾客或任意会员卡都可使用。若未来启用,将以分隔的 ID 列表形式记录限定卡种。 | 来源: card_type_ids | 角色: 外键(潜在指向卡种维)';
+
+-- dim_groupbuy_package_Ex
+CREATE TABLE IF NOT EXISTS dim_groupbuy_package_Ex (
+ groupbuy_package_id BIGINT,
+ site_name VARCHAR(100),
+ usable_count INTEGER,
+ date_type INTEGER,
+ usable_range VARCHAR(255),
+ date_info VARCHAR(255),
+ start_clock VARCHAR(16),
+ end_clock VARCHAR(16),
+ add_start_clock VARCHAR(16),
+ add_end_clock VARCHAR(16),
+ area_tag_type INTEGER,
+ table_area_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_area_id_list VARCHAR(512),
+ group_type INTEGER,
+ system_group_type INTEGER,
+ package_type INTEGER,
+ effective_status INTEGER,
+ max_selectable_categories INTEGER,
+ creator_name VARCHAR(100),
+ SCD2_start_time TIMESTAMPTZ,
+ SCD2_end_time TIMESTAMPTZ,
+ SCD2_is_current INT,
+ SCD2_version INT,
+ PRIMARY KEY (groupbuy_package_id)
+);
+COMMENT ON COLUMN dim_groupbuy_package_Ex.groupbuy_package_id IS '门店侧团购套餐主键。每条记录一个套餐定义,供团购券核销记录指向。平台验券记录中的 group_package_id 通常指向这里。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.site_name IS '门店名称,当前均为“朗朗桌球”。属于冗余展示字段,可用于报表标题。 | 来源: site_name';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_count IS '可使用次数上限。当前全部为 9999999,用作“无限次使用”的哨兵值。若未来限制次数,只需配置为具体次数。 | 来源: usable_count';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_type IS '日期限制类型枚举。当前样本全部为 1。推测常见含义:1 表示“全部日期可用”;其他值可用于区分工作日、周末或指定日期等模式。 | 来源: date_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.usable_range IS '日期范围说明的文本,例如“周一至周五”等。当前全部为空字符串,实际规则由 date_type 与时间段字段控制。 | 来源: usable_range';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.date_info IS '更细粒度的日期信息,可能用于存储具体日期列表或节假日规则,形式可能是编码或 JSON 字符串。当前几乎全部为空,仅有极少记录为“0”。 | 来源: date_info';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.start_clock IS '每日可用时间段的起始时间(第一段),字符串格式 HH:MM:SS,例如“10:00:00”“00:00:00”。与 end_clock 组合定义日内时段。 | 来源: start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.end_clock IS '每日可用时间段的结束时间(第一段),字符串格式 HH:MM:SS。与 start_clock 共同描述第一段可用时段。 | 来源: end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_start_clock IS '附加可用时段的起始时间(第二段),格式 HH:MM:SS。当前样本常见值为“00:00:00”或“10:00:00”。用于配置早场加夜场等双时段场景。 | 来源: add_start_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.add_end_clock IS '附加可用时段的结束时间(第二段)。常见值如“1.00:00:00”“18:00:00”“23:59:00”。其中“1.00:00:00”表示跨至次日零点,用于表示“可用到第二天凌晨”的场景。 | 来源: add_end_clock';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.area_tag_type IS '区域标记类型枚举。当前样本全部为 1。推测 1 表示“按台区标签限制”(如 A 区、B 区、中八、斯诺克、包厢、KTV 等)。其他取值可能对应按具体台桌或其它规则限用。 | 来源: area_tag_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id IS '单一台区 ID。当前样本全部为 0。原始设计用于限定只能在一个具体区域使用,但由于已引入多选逻辑,实际使用已迁移到 tenant_table_area_id_list。 | 来源: table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.tenant_table_area_id IS '租户级台区 ID,单值版本。当前样本全部为 0。与 table_area_id 类似,已被多选列表字段取代。 | 来源: tenant_table_area_id';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.table_area_id_list IS '门店级台区 ID 列表。当前样本全部为空字符串。根据命名推测原本用于存储多个 table_area_id,实际实现已转向租户维度列表字段。 | 来源: table_area_id_list';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.group_type IS '团购类型枚举。当前样本全部为 1。推测 1 表示“计时类/台费类套餐”。其他取值可能用于商品类套餐、代金券类等,需结合系统配置进一步确认。 | 来源: group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.system_group_type IS '系统级团购类型枚举。当前样本全部为 1。推测 1 表示“券码类团购”,即通过券码核销。其他取值可能为卡内套餐、内部套餐等,具体含义有待业务确认。 | 来源: system_group_type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.package_type IS '内部业务子类型枚举。样本中取值有 1 与 2,各占比不同。具体含义不明,可能区分不同产品线或套餐来源,例如“平台合作套餐”与“自定义套餐”等,需要参考业务文档。 | 来源: type';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.effective_status IS '当前有效状态枚举,由系统根据时间及配置动态计算。观测值:1 表示当前有效,可正常核销;3 表示失效或已过期(即使 is_enabled 仍为 1,也不可使用)。可用于分析时过滤失效套餐。 | 来源: effective_status';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.max_selectable_categories IS '最大可选择分类数或子项数,具体含义未在样本和说明中体现,当前值全部为 0。可能用于“组合型套餐”中限制可选项目数量。 | 来源: max_selectable_categories';
+COMMENT ON COLUMN dim_groupbuy_package_Ex.creator_name IS '创建人名称,例如“店长:郑丽珊”。主要用于审计追踪和后台展示。 | 来源: creator_name';
+
+-- dwd_settlement_head
+CREATE TABLE IF NOT EXISTS dwd_settlement_head (
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_name VARCHAR(100),
+ table_id BIGINT,
+ settle_name VARCHAR(100),
+ order_trade_no BIGINT,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ settle_type INTEGER,
+ revoke_order_id BIGINT,
+ member_id BIGINT,
+ member_name VARCHAR(100),
+ member_phone VARCHAR(50),
+ member_card_account_id BIGINT,
+ member_card_type_name VARCHAR(100),
+ is_bind_member BOOLEAN,
+ member_discount_amount NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ pay_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head.tenant_id IS '租户/商户 ID(品牌维度),与各业务 JSON 中的 tenantId 一致。 | 来源: settleList.tenantId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_id IS '门店 ID,用于关联门店维表 dim_site。 | 来源: settleList.siteId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.site_name IS '门店名称快照,冗余展示字段,推荐通过 site_id 关联维表获取标准名称。 | 来源: settleList.siteName';
+COMMENT ON COLUMN dwd_settlement_head.table_id IS '结账关联的桌台 ID,对应台桌维表 dim_site_table 的主键。 | 来源: settleList.tableId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.settle_name IS '结账对象名称,一般为 “区域 + 桌号”,如 “A区 A17”,便于报表展示。 | 来源: settleList.settleName';
+COMMENT ON COLUMN dwd_settlement_head.order_trade_no IS '交易号 / 订单流水号,与台费、助教等明细中的 order_trade_no 一致,用于按“交易维度”串联各业务明细。 | 来源: settleList.settleRelateId';
+COMMENT ON COLUMN dwd_settlement_head.create_time IS '结账创建时间(收银端点击“确认结账”的时间),格式:YYYY-MM-DD HH:MM:SS。 | 来源: settleList.createTime';
+COMMENT ON COLUMN dwd_settlement_head.pay_time IS '实际支付完成时间,通常晚于 create_time,用于资金结算及对账分析。 | 来源: settleList.payTime';
+COMMENT ON COLUMN dwd_settlement_head.settle_type IS '结账类型枚举。样本中主要有:1=正常结账;3=特殊类型结账(如挂账、补单、调整单等,具体需业务确认)。 | 来源: settleList.settleType';
+COMMENT ON COLUMN dwd_settlement_head.revoke_order_id IS '若当前记录属于撤销链路,记录对应的撤销单或原单的结账 ID,形成自关联关系。样本中为 0。 | 来源: settleList.revokeOrderId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_id IS '会员主键 ID,一般对应租户维度的会员 ID,用于关联 dim_member。 | 来源: settleList.memberId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_name IS '会员姓名快照,冗余展示字段;当前样本多为空,推荐通过关联会员维表获取标准姓名。 | 来源: settleList.memberName';
+COMMENT ON COLUMN dwd_settlement_head.member_phone IS '会员手机号快照,冗余展示字段,通常通过会员维表获取更可靠。 | 来源: settleList.memberPhone';
+COMMENT ON COLUMN dwd_settlement_head.member_card_account_id IS '会员卡账户 ID,对应 dim_member_card_account 主键;当前样本多为 0,但结构上是“结账 → 具体卡账户”的外键。 | 来源: settleList.tenantMemberCardId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head.member_card_type_name IS '会员卡类型名称快照,如“储值卡”“次卡”等,便于前端展示和报表查看。 | 来源: settleList.memberCardTypeName';
+COMMENT ON COLUMN dwd_settlement_head.is_bind_member IS '本单是否绑定会员。0=否(散客);1=是(存在 member_id)。样本中多为 0。 | 来源: settleList.isBindMember';
+COMMENT ON COLUMN dwd_settlement_head.member_discount_amount IS '会员折扣产生的优惠金额(元),例如会员卡折扣减免的台费/商品金额,参与整单优惠拆分。 | 来源: settleList.memberDiscountAmount';
+COMMENT ON COLUMN dwd_settlement_head.consume_money IS '本次结账消费总额(原价小计),约等于台费 + 商品 + 助教 + 服务等项目原价金额之和,未扣除任何优惠。 | 来源: settleList.consumeMoney';
+COMMENT ON COLUMN dwd_settlement_head.table_charge_money IS '本单台费(桌台计费部分)的金额(原价侧)。 | 来源: settleList.tableChargeMoney';
+COMMENT ON COLUMN dwd_settlement_head.goods_money IS '本单商品销售原价金额,对应酒水、小吃等商品类消费。 | 来源: settleList.goodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.real_goods_money IS '商品实际计入金额,通常为 goods_money 扣除部分促销/折扣之后的金额。 | 来源: settleList.realGoodsMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_pd_money IS '助教“排钟 / 点钟 / 按时长服务”等项目的应计金额(原价侧),与助教流水中的 ledger_amount 汇总对应。 | 来源: settleList.assistantPdMoney';
+COMMENT ON COLUMN dwd_settlement_head.assistant_cx_money IS '助教“超休”类助教项目金额(原价侧),是对助教收入的补充拆分维度,具体业务定义需结合助教模块确认。 | 来源: settleList.assistantCxMoney';
+COMMENT ON COLUMN dwd_settlement_head.adjust_amount IS '手动减免,人工调价金额汇总(整单减免或特殊价格调整),通常正值表示减免额度。 | 来源: settleList.adjustAmount';
+COMMENT ON COLUMN dwd_settlement_head.pay_amount IS '本单顾客“实付金额”(不含券面值这类虚拟抵扣),等于各支付渠道金额之和减去退款等调整。 | 来源: settleList.payAmount';
+COMMENT ON COLUMN dwd_settlement_head.balance_amount IS '从会员储值余额账户中扣除的金额(储值卡消费部分)。 | 来源: settleList.balanceAmount';
+COMMENT ON COLUMN dwd_settlement_head.recharge_card_amount IS '充值卡支付金额(使用充值类卡片余额支付的金额),与储值/充值型卡资金来源相关。 | 来源: settleList.rechargeCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.gift_card_amount IS '礼品卡或代金卡支付金额。 | 来源: settleList.giftCardAmount';
+COMMENT ON COLUMN dwd_settlement_head.coupon_amount IS '本单由优惠券(团购券、代金券等)实际抵扣的金额。 | 来源: settleList.couponAmount';
+COMMENT ON COLUMN dwd_settlement_head.rounding_amount IS '抹零 / 四舍五入产生的金额差值,例如按角、分抹零。 | 来源: settleList.roundingAmount';
+COMMENT ON COLUMN dwd_settlement_head.point_amount IS '积分相关金额或数量。根据系统配置可能表示“使用积分抵扣的金额”或“本单获得的积分折算金额”,文档未给出唯一定义。 | 来源: settleList.pointAmount';
+
+-- dwd_settlement_head_Ex
+CREATE TABLE IF NOT EXISTS dwd_settlement_head_Ex (
+ order_settle_id BIGINT,
+ serial_number INTEGER,
+ settle_status INTEGER,
+ can_be_revoked BOOLEAN,
+ revoke_order_name VARCHAR(100),
+ revoke_time TIMESTAMPTZ,
+ is_first_order BOOLEAN,
+ service_money NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ online_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ payment_method INTEGER,
+ coupon_sale_amount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ is_activity BOOLEAN,
+ operator_name VARCHAR(100),
+ salesman_name VARCHAR(100),
+ order_remark VARCHAR(255),
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ PRIMARY KEY (order_settle_id)
+);
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_settle_id IS '结账记录主键 ID(订单结算 ID),全系统统一的结账单号,用于关联台费流水、助教流水、小票等明细表。 | 来源: settleList.id | 角色: 主键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.serial_number IS '结账序列号或打印序号,当前样本全部为 0,具体业务用途未在文档中明确。 | 来源: settleList.serialNumber';
+COMMENT ON COLUMN dwd_settlement_head_Ex.settle_status IS '结账状态枚举。当前样本值均为 2,表示“已结算/已完成”;其他取值及含义未在样本和文档中出现,需后续补充。 | 来源: settleList.settleStatus';
+COMMENT ON COLUMN dwd_settlement_head_Ex.can_be_revoked IS '本单是否仍允许撤销/冲正。0=否;1=是。样本中均为 0。主要用于运维控制,分析价值有限。 | 来源: settleList.canBeRevoked';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_order_name IS '撤销单名称/标识,用于人工识别撤销关系;当前样本为空。 | 来源: settleList.revokeOrderName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.revoke_time IS '撤销时间。无撤销时通常为系统默认值(如 0001-01-01 00:00:00)。 | 来源: settleList.revokeTime';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_first_order IS '是否首单(新客首单)标记。0=否;1=是。当前样本全部为 0,且文档中说明为“推测用途”,具体业务定义需确认。 | 来源: settleList.isFirst';
+COMMENT ON COLUMN dwd_settlement_head_Ex.service_money IS '其他服务费金额(如包间服务费等),用于与台费、商品、助教金额区分。 | 来源: settleList.serviceMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.cash_amount IS '现金支付金额。 | 来源: settleList.cashAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.card_amount IS '刷卡类支付金额(如银行卡/信用卡等),具体包含哪些通道需结合支付模块确认。 | 来源: settleList.cardAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.online_amount IS '线上支付金额汇总(如微信、支付宝、云闪付等),不区分具体通道。 | 来源: settleList.onlineAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.refund_amount IS '本单涉及的退款金额(元)。普通正常结账为 0,退单或部分退款时为正数。 | 来源: settleList.refundAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.prepay_money IS '本单使用的预付金/定金金额。 | 来源: settleList.prepayMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.payment_method IS '支付方式整体标记(枚举)。当前样本值统一为 0,具体各枚举值对应的支付方式未在文档中说明,需业务确认。 | 来源: settleList.paymentMethod';
+COMMENT ON COLUMN dwd_settlement_head_Ex.coupon_sale_amount IS '优惠券本身的售卖金额/成本金额(例如顾客为购买套餐券支付的金额),当前样本多为 0。 | 来源: settleList.couponSaleAmount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.all_coupon_discount IS '所有券类优惠折扣的汇总金额,用于统计“券优惠总额”。 | 来源: settleList.allCouponDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.goods_promotion_money IS '商品促销产生的优惠金额(如满减、买赠均摊到商品部分)。 | 来源: settleList.goodsPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_promotion_money IS '助教项目参与活动/促销产生的优惠金额。 | 来源: settleList.assistantPromotionMoney';
+COMMENT ON COLUMN dwd_settlement_head_Ex.activity_discount IS '整单活动折扣金额(如整单打折、满减活动产生的优惠),不区分具体项目类别。 | 来源: settleList.activityDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.assistant_manual_discount IS '针对助教服务的人工减免金额,与一般商品/台费折扣区分开。 | 来源: settleList.assistantManualDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_price IS '积分抵扣对应的金额(售价侧),记录因积分使用而减少的应收金额。 | 来源: settleList.pointDiscountPrice';
+COMMENT ON COLUMN dwd_settlement_head_Ex.point_discount_cost IS '积分抵扣对应的成本金额(成本侧),用于毛利和利润分析。 | 来源: settleList.pointDiscountCost';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_coupon IS '是否使用优惠券。0=未使用;1=使用。当前样本均为 0。 | 来源: settleList.isUseCoupon';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_use_discount IS '是否使用折扣(包括会员折扣或其他整单折扣)。0=未使用;1=使用。当前样本多为 0。 | 来源: settleList.isUseDiscount';
+COMMENT ON COLUMN dwd_settlement_head_Ex.is_activity IS '是否参与营销活动。0=未参与;1=参与。 | 来源: settleList.isActivity';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_name IS '结账操作员名称快照(通常带角色前缀,如“收银员:张三”),用于报表展示。 | 来源: settleList.operatorName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_name IS '营业员/业务员名称,用于业绩归属及提成分析;样本中多为空。 | 来源: settleList.salesManName';
+COMMENT ON COLUMN dwd_settlement_head_Ex.order_remark IS '订单备注,由收银员手工填写的文字说明,如特殊情况、赠送原因等,主要用于人工复盘。 | 来源: settleList.orderRemark';
+COMMENT ON COLUMN dwd_settlement_head_Ex.operator_id IS '结账操作员用户 ID,用于关联员工/账号维度(如 dim_staff)。 | 来源: settleList.operatorId | 角色: 外键';
+COMMENT ON COLUMN dwd_settlement_head_Ex.salesman_user_id IS '营业员用户 ID,可关联员工维度,用于业绩分析和提成计算。 | 来源: settleList.salesManUserId | 角色: 外键';
+
+-- dwd_table_fee_log
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log (
+ table_fee_log_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ site_table_area_id BIGINT,
+ site_table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ member_id BIGINT,
+ ledger_name VARCHAR(64),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ real_table_charge_money NUMERIC(18,2),
+ coupon_promotion_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ real_table_use_seconds INTEGER,
+ add_clock_seconds INTEGER,
+ start_use_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log.order_trade_no IS '订单交易号。整笔订单的主编号,用于把同一订单下的台费、商品、助教等多种明细串联在一起。可与支付记录中的交易号对应。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_settle_id IS '结算单号 / 结账 ID。对应一次完整的结账操作。与 dwd_settlement_head 的主键关联。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.order_pay_id IS '订单支付记录 ID。对应支付记录中的 id 或 relate_id(视具体模型)。用于追踪这条台费最终对应哪一条支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_id IS '租户 / 品牌 ID。本文件内所有记录属于同一租户。与其他表的 tenant_id 一致,用于品牌级过滤。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_id IS '门店 ID。当前样本为同一门店。与嵌套的 siteProfile.id 以及其他 JSON 中的 site_id 对应,用于门店维度关联。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_id IS '桌台 ID。对应“台桌基础表”的主键。用于确定具体哪一张台或包厢。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_id IS '门店内“台桌区域” ID(门店视角的区域,如 A 区、B 区、斯诺克区、包厢区)。与门店内部的区域维度对应。 | 来源: site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.site_table_area_name IS '台桌区域名称,如 “A区”“B区”“斯诺克区”“VIP包厢” 等。主要用于报表展示和人工阅读。 | 来源: site_table_area_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.tenant_table_area_id IS '租户层面的台桌区域 ID。用于品牌层统一定义的区域配置(一个区域可在多门店复用)。对应租户级区域维度。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.member_id IS '会员 ID。多数为 0 表示散客。非 0 时表示关联会员:0 表示散客或未使用会员;>0 对应会员档案中的 id。用于将台费流水关联到 dim_member。 | 来源: member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_name IS '台号名称,例如 “A1”“A2”“S1”“VIP包厢” 等。等价于桌台维表中的展示名称,冗余在流水中作为快照。 | 来源: ledger_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_unit_price IS '台费结算时的计费单价(元/小时或元/单位时长)。与 ledger_count 配合计算原始应收台费。常见值如 48.0、58.0、68.0、88.0、98.0、116.0 等。 | 来源: ledger_unit_price | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_count IS '计费时长单位数。与 ledger_unit_price 共同决定原始应收额。可与 real_table_use_seconds 换算关系约为:时长秒数 ≈ ledger_count × 计费粒度(例如 30 分钟、60 分钟)。 | 来源: ledger_count | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_amount IS '原始应收台费金额,按单价与计费时长计算出来的台费金额,尚未考虑会员、券、调账等各类优惠拆分。 | 来源: ledger_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_charge_money IS '实际向顾客收取的台费金额(现金 / 实付维度),不含券方承担、会员承担和内部调账部分。若为 0,则该笔台费完全由券、会员或内部调账承担。 | 来源: real_table_charge_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.coupon_promotion_amount IS '由优惠券、活动、团购等促销承担的优惠金额,直接抵扣在台费上。常见值为与单价或整倍数相同,例如 48.0、96.0、136.0、144.0 等。若 real_table_charge_money 为 0 且该字段等于 ledger_amount,说明台费完全由促销承担。 | 来源: coupon_promotion_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.member_discount_amount IS '由会员权益产生的优惠金额,例如会员折扣、会员免费台等。若 ledger_amount = real_table_charge_money = member_discount_amount,表示这笔台费由会员权益承担,但仍作为台费收入进行记录。 | 来源: member_discount_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.adjust_amount IS '手动减免,调整金额 / 调账金额。用于将台费金额转移或冲减到其他项目(例如套餐、包厢统一计费)或做手工调整。若 ledger_amount 完全被 adjust_amount 抵消,则说明该笔台费被整体调出当前台费科目。 | 来源: adjust_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.real_table_use_seconds IS '台费实际计费时长(秒)。用于计算台费单价与费率分析。内部统一以秒为单位。 | 来源: real_table_use_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.add_clock_seconds IS '加钟时长(秒)。在原有使用基础上追加的累计加钟时长,常见为 2400、4200 等 60 的倍数(对应 40 分钟、70 分钟等)。 | 来源: add_clock_seconds | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.start_use_time IS '台开始使用时间,即实际开台时间。与 ledger_start_time 相同,表示计费起算点。 | 来源: start_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_end_time IS '台账计费结束时间。通常与 last_use_time 相差 1 秒。可理解为系统为计费进行的截断时刻。 | 来源: ledger_end_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.create_time IS '台费流水记录创建时间,通常接近结账时间。用于区分计费期间与结账时间。 | 来源: create_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.ledger_status IS '台费状态。样本中全部为 1。含义:1 表示正常已结算台费。按命名推断,0 可能表示未结算,2 可能表示作废或撤销,需要结合后续数据确认。 | 来源: ledger_status | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_single_order IS '是否独立计费单元。枚举:1 表示该记录是独立结算的桌费;0 表示非独立结算条目(可能是合并结账、转台过程中的占位记录)。is_single_order = 0 的记录通常 ledger_count 与 real_table_use_seconds 为 0。 | 来源: is_single_order | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log.is_delete IS '逻辑删除标志。0 表示未删除(有效记录);1 表示已逻辑删除(一般不参与统计)。当前样本全部为 0。 | 来源: is_delete | 角色: 无';
+
+-- dwd_table_fee_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_log_Ex (
+ table_fee_log_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_name VARCHAR(64),
+ used_card_amount NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ mgmt_fee NUMERIC(18,2),
+ fee_total NUMERIC(18,2),
+ ledger_start_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ operator_id BIGINT,
+ salesman_user_id BIGINT,
+ salesman_org_id BIGINT,
+ PRIMARY KEY (table_fee_log_id)
+);
+COMMENT ON COLUMN dwd_table_fee_log_Ex.table_fee_log_id IS '台费流水记录主键。每一条台费使用记录唯一一条。对应一次“台费计费单元”。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_name IS '操作员姓名。为冗余展示字段,便于直接阅读而不必联表员工档案。 | 来源: operator_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_name IS '营业员姓名。当前样本为空。用于需要对营业员维度做业绩统计时作为冗余展示。 | 来源: salesman_name | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.used_card_amount IS '由储值卡、次卡等“卡内余额”直接抵扣到台费的金额。当前样本为 0,但语义明确,用于区分“卡扣款”与“现金收款”。 | 来源: used_card_amount | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.service_money IS '服务费 / 成本 /分成金额字段,类似助教流水里的 service_money。当前样本全为 0,门店未启用该字段,未来可能用于台费附加服务费或分成计算。 | 来源: service_money | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.mgmt_fee IS '管理费字段。当前样本为 0。推测用于未来支持“台费附加管理费”功能。尚未实际启用。 | 来源: mgmt_fee | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.fee_total IS '附加费用合计值字段。当前样本为 0。设计上用于汇总管理费、服务费等附加费用。尚未实际启用。 | 来源: fee_total | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.ledger_start_time IS '台账计费起始时间。当前样本与 start_use_time 相同,表示计费与开台同时开始。 | 来源: ledger_start_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.last_use_time IS '最后使用 / 操作时间,通常略晚于 ledger_end_time。可视为客人最后一次用台或最后一次加钟/操作的时间点。 | 来源: last_use_time | 角色: 无';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.operator_id IS '操作员 ID。负责开台 / 结账的员工账号 ID。与员工 / 账号体系中的用户 ID 对应。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_user_id IS '营业员用户 ID。目前样本值为 0,表示门店暂未使用此字段做提成员工归属,但语义清晰。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_log_Ex.salesman_org_id IS '营业员所属机构 / 部门 ID。目前样本为 0。用于员工组织结构统计时的归属。 | 来源: salesman_org_id | 角色: 外键';
+
+-- dwd_table_fee_adjust
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust (
+ table_fee_adjust_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ table_area_name VARCHAR(64),
+ tenant_table_area_id BIGINT,
+ ledger_amount NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ adjust_time TIMESTAMPTZ,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_trade_no IS '订单交易号;与台费流水、结账记录等表中的同名字段一致,用于把本次台费调整挂到具体订单上。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.order_settle_id IS '结算单 / 小票 ID;与小票、结账头表中的 order_settle_id 对应,用于关联同一次结账。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_id IS '租户 / 品牌 ID;标识该记录属于哪一个商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.site_id IS '门店 ID;与 dim_site、其它业务事实表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_id IS '台桌 ID;与 dim_table(site_tables_master.id)以及各类台费、助教流水中的 site_table_id 对应,标识哪一张台发生了折扣/调账。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_id IS '门店维度的台桌区域 ID;与 dim_table 中的 site_table_area_id 对应,例如 “斯诺克区”“VIP包厢”等区域。 | 来源: tableProfile.site_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.table_area_name IS '台桌区域名称快照,例如 “斯诺克区”“A区”“VIP包厢”;冗余展示字段,可从 dim_table 通过 table_area_id 获取。 | 来源: tableProfile.site_table_area_name';
+COMMENT ON COLUMN dwd_table_fee_adjust.tenant_table_area_id IS '租户维度的“台桌区域 ID”;同一租户下跨门店复用的区域标识,用于在租户级别统计各区域的折扣分布。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_amount IS '台费调整金额;等于台费流水中对应记录的 adjust_amount。正数表示被减免/调账掉的台费金额(本批数据全部为正);是衡量台费折扣规模的核心度量。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_table_fee_adjust.ledger_status IS '调整记录状态(枚举)。1:生效调整(当前有效的折扣/调账记录);0:失效/被覆盖的历史记录(同一订单有多次调整时,旧记录会标记为 0,仅最新一条为 1)。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_table_fee_adjust.is_delete IS '逻辑删除标记(枚举)。0:未删除(有效记录);1:已逻辑删除(后台标记删除,不再参与业务统计)。当前数据全部为 0,但字段需保留以适配长期数据。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_table_fee_adjust.adjust_time IS '台费调整记录创建时间,即打折/调账操作被系统写入的时间戳,用于时间分析和与结账时间对比(判断是事前折扣还是事后调账)。 | 来源: create_time';
+
+-- dwd_table_fee_adjust_Ex
+CREATE TABLE IF NOT EXISTS dwd_table_fee_adjust_Ex (
+ table_fee_adjust_id BIGINT,
+ adjust_type INTEGER,
+ ledger_count INTEGER,
+ ledger_name VARCHAR(128),
+ applicant_name VARCHAR(64),
+ operator_name VARCHAR(64),
+ applicant_id BIGINT,
+ operator_id BIGINT,
+ PRIMARY KEY (table_fee_adjust_id)
+);
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.table_fee_adjust_id IS '台费折扣 / 调整流水主键;一条台费打折或调账操作对应一条记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.adjust_type IS '调整类型(枚举)。当前数据全部为 1。取值示例:1:台费打折 / 台费减免(本门店实际使用的唯一类型);其他值:预留给台费转移、误操作恢复等其他类型(当前未出现,仅推测)。 | 来源: adjust_type';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_count IS '调整次数计数,本数据中恒为 1,表示“一次调整事件”;与台费流水中的 ledger_count(计时长)含义不同。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.ledger_name IS '调账项目名称或打折原因名称(设计意图);当前门店所有记录值为空字符串,未实际使用。作用暂不明确,保留以备后续业务启用。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_name IS '申请人姓名快照,通常包含角色前缀(如 “收银员:张三”);是 applicant_id 的冗余展示字段,实际名称应以员工维表为准。 | 来源: applicant_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_name IS '操作员姓名快照;与 operator_id 对应的姓名冗余字段。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.applicant_id IS '申请人 ID;发起本次台费折扣/调账的员工账号 ID,用于按员工维度统计折扣行为。 | 来源: applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_table_fee_adjust_Ex.operator_id IS '实际执行调账操作的操作员 ID;当前样本中与 applicant_id 相同,但模型上允许“申请人 ≠ 操作人”。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_store_goods_sale
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale (
+ store_goods_sale_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_goods_id BIGINT,
+ site_id BIGINT,
+ tenant_id BIGINT,
+ site_goods_id BIGINT,
+ tenant_goods_id BIGINT,
+ tenant_goods_category_id BIGINT,
+ tenant_goods_business_id BIGINT,
+ site_table_id BIGINT,
+ ledger_name VARCHAR(200),
+ ledger_group_name VARCHAR(100),
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ discount_price NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ cost_money NUMERIC(18,2),
+ ledger_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (store_goods_sale_id)
+);
+COMMENT ON COLUMN dwd_store_goods_sale.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_trade_no IS '订单交易号(业务单号);与台费、助教、团购等表的 order_trade_no 一致,用于把同一订单下各类消费串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_settle_id IS '结账记录主键 ID;连接结账记录 / 结算头事实表。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_pay_id IS '支付记录 ID;连接支付流水事实表,用于还原本条销售对应的收款信息。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.order_goods_id IS '当前版本的订单内商品明细 ID;可在订单范围内唯一定位该商品行,用于与小票明细等做行级关联。 | 来源: order_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_id IS '门店 ID(系统主键);与其它流水表中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_id IS '租户/品牌 ID;同一品牌下多门店共享同一个 tenant_id。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_goods_id IS '门店级商品 ID;连接门店商品档案 dim_store_goods,与库存变动记录中的 siteGoodsId 一致。 | 来源: site_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_id IS '租户级(品牌级)商品 ID;连接租户级商品档案维度表,一个 tenant_goods_id 在不同门店可对应多个 site_goods_id。 | 来源: tenant_goods_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_category_id IS '租户级商品一级分类 ID;连接商品分类维度(如酒水、零食等)。 | 来源: tenant_goods_category_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.tenant_goods_business_id IS '租户级商品业务大类 ID(更高一层的业务分类,如“零食类”“酒水类”等)。 | 来源: tenant_goods_business_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.site_table_id IS '球台 ID;非 0 表示该商品在某张台桌上点单,0 表示前台售卖或与台桌无关。连接台桌维度 dim_table。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_name IS '销售项目名称(商品名),如“哇哈哈矿泉水”“地道肠”等;为当时销售时刻的名称快照。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_group_name IS '门店前台菜单分组名称,如“酒水”“零食”“小吃”等;与品牌统一分类是两套维度。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_unit_price IS '结算单价(元/单位);本次销售实际使用的单价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_count IS '销售数量(以商品单位计),如 1、2、6、36 等。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_amount IS '原始应收金额(未考虑任何折扣/抵扣),通常接近 ledger_unit_price × ledger_count。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_store_goods_sale.discount_price IS '折后单价(元/单位);无折扣时等于 ledger_unit_price,有折扣时小于 ledger_unit_price。 | 来源: discount_price';
+COMMENT ON COLUMN dwd_store_goods_sale.real_goods_money IS '本行商品实际入账金额(已考虑折扣及其他抵扣后,实际计入营业额的金额);一定不大于 ledger_amount。 | 来源: real_goods_money';
+COMMENT ON COLUMN dwd_store_goods_sale.cost_money IS '本行商品对应的成本金额,用于毛利和利润分析;源自商品档案成本价及成本核算逻辑。 | 来源: cost_money';
+COMMENT ON COLUMN dwd_store_goods_sale.ledger_status IS '销售流水状态:1=正常有效;其他数值(当前数据未出现)一般表示“待结算”“作废”等。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_store_goods_sale.is_delete IS '逻辑删除标志:0=正常有效;1=已删除(仅保留历史,不再参与前端展示及统计)(本批数据全部为 0)。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_store_goods_sale.create_time IS '销售记录创建时间,通常为结账时间或录入时间;用于时间维度分析,与订单层时间字段对齐。 | 来源: create_time';
+
+-- dwd_store_goods_sale_Ex
+CREATE TABLE IF NOT EXISTS dwd_store_goods_sale_Ex (
+ store_goods_sale_id BIGINT,
+ legacy_order_goods_id BIGINT,
+ site_name TEXT,
+ legacy_site_id BIGINT,
+ goods_remark TEXT,
+ option_value_name TEXT,
+ operator_name TEXT,
+ open_salesman_flag INTEGER,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ discount_money NUMERIC(18,2),
+ returns_number INTEGER,
+ coupon_deduct_money NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_money NUMERIC(18,2),
+ point_discount_money_cost NUMERIC(18,2),
+ package_coupon_id BIGINT,
+ order_coupon_id BIGINT,
+ member_coupon_id BIGINT,
+ option_price NUMERIC(18,2),
+ option_member_discount_money NUMERIC(18,2),
+ option_coupon_deduct_money NUMERIC(18,2),
+ push_money NUMERIC(18,2),
+ is_single_order INTEGER,
+ sales_type INTEGER,
+ operator_id BIGINT
+);
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.store_goods_sale_id IS '商品销售明细主键;每条记录代表一次订单中的一个商品行流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_order_goods_id IS '旧版订单商品明细 ID,兼容字段;当前接口已统一使用 order_goods_id,本批数据全部为 0。 | 来源: orderGoodsId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.site_name IS '门店名称,对 site_id 的冗余文本(例如“朗朗桌球”),用于展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.legacy_site_id IS '历史兼容门店 ID;当前接口统一使用 site_id,本批数据 siteId 全部为 0。 | 来源: siteId';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.goods_remark IS '商品备注/口味说明/特殊说明;部分记录为空,部分与商品名相同。 | 来源: goods_remark';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_value_name IS '商品选项名称(规格/口味,如大杯/小杯、不加冰等);当前门店未启用多规格,样本中全部为空。 | 来源: option_value_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_name IS '操作员姓名冗余,如“收银员:郑丽珊”;用于展示,不作为关联键。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.open_salesman_flag IS '是否启用营业员机制标志:1=启用营业员/提成体系(需指定 salesman_* 字段);2=未启用营业员体系(本批数据全部为 2)。 | 来源: openSalesman';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_user_id IS '营业员用户 ID(系统账号 ID);当前样本全部为 0,说明门店未启用营业员业绩统计。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_name IS '营业员姓名;当前样本全部为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_role_id IS '营业员角色 ID(例如某角色代码对应“销售员”角色);当前样本全部为 0。 | 来源: salesman_role_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.salesman_org_id IS '营业员所属组织/部门 ID;当前样本全部为 0,未启用按组织分组统计。 | 来源: sales_man_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.discount_money IS '本行商品的直接价格优惠金额(打折让利部分);在简单场景下满足:ledger_amount − discount_money ≈ real_goods_money(不含积分、券抵扣)。 | 来源: discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.returns_number IS '退货数量;当前样本全部为 0,如发生退货则记录退回的件数。 | 来源: returns_number';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.coupon_deduct_money IS '优惠券/团购券直接抵扣到本条商品明细上的金额;当前样本为 0,说明券更多在订单级处理。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_discount_amount IS '由会员折扣针对本行商品产生的优惠金额;当前样本全部为 0,折扣通常体现在 discount_money 中。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money IS '由积分抵扣的金额(顾客用积分兑换的抵现金额)。 | 来源: point_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.point_discount_money_cost IS '积分抵扣对应的成本金额(积分成本、营销费用等核算用)。 | 来源: point_discount_money_cost';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.package_coupon_id IS '套餐券 ID;当商品来自套餐拆分或与套餐券关联时,用于追溯对应的套餐业务(当前样本为 0)。 | 来源: package_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.order_coupon_id IS '订单级优惠券 ID;整单使用某张券时,可用于记录该券对本行商品的分摊关系(当前样本为 0)。 | 来源: order_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.member_coupon_id IS '会员券 ID(如会员专享优惠券);当前样本为 0,为会员权益预留字段。 | 来源: member_coupon_id';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_price IS '商品选项(规格/加料等)的附加价格;当前门店未启用此功能,样本为 0。 | 来源: option_price';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_member_discount_money IS '由会员折扣作用在“选项价格”上的优惠金额;当前样本为 0。 | 来源: option_member_discount_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.option_coupon_deduct_money IS '由优惠券抵扣“选项价格”的金额;当前样本为 0。 | 来源: option_coupon_deduct_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.push_money IS '本行商品对应的提成金额(营业员/业务员提成);当前样本为 0,说明提成体系未启用。 | 来源: push_money';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.is_single_order IS '是否作为独立明细参与订单结算:1=作为独立明细参与订单;0=在特殊业务中可能合并为打包项目(当前样本全部为 1)。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.sales_type IS '销售类型:1=正常销售(当前样本全部为 1);常见扩展用法:2=赠品;3=内部消耗;4=盘点调整等。 | 来源: sales_type';
+COMMENT ON COLUMN dwd_store_goods_sale_Ex.operator_id IS '操作员 ID(录入本条销售的员工);与其它流水中的 operator_id 一致,可统一做员工维度分析。 | 来源: operator_id | 角色: 外键';
+
+-- dwd_assistant_service_log
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log (
+ assistant_service_id BIGINT,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_pay_id BIGINT,
+ order_assistant_id BIGINT,
+ order_assistant_type INTEGER,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ site_table_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ assistant_no VARCHAR(64),
+ nickname VARCHAR(64),
+ site_assistant_id BIGINT,
+ user_id BIGINT,
+ assistant_team_id BIGINT,
+ person_org_id BIGINT,
+ assistant_level INTEGER,
+ level_name VARCHAR(64),
+ skill_id BIGINT,
+ skill_name VARCHAR(64),
+ ledger_unit_price NUMERIC(10,2),
+ ledger_amount NUMERIC(10,2),
+ projected_income NUMERIC(10,2),
+ coupon_deduct_money NUMERIC(10,2),
+ income_seconds INTEGER,
+ real_use_seconds INTEGER,
+ add_clock INTEGER,
+ create_time TIMESTAMPTZ,
+ start_use_time TIMESTAMPTZ,
+ last_use_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_trade_no IS '订单交易号,用于与台费、商品、支付等同一订单下的其他明细串联。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_settle_id IS '结算单号,对应结账记录、小票中的结算主键。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_pay_id IS '支付记录主键 ID,用于关联支付流水。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_id IS '订单中“助教项目明细”的内部 ID,一笔订单中多段助教服务时用于区分。 | 来源: order_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.order_assistant_type IS '助教服务类型枚举:1 表示常规助教服务(如基础课);2 表示附加类助教服务(如附加课);其他值预留。 | 来源: order_assistant_type';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_id IS '租户/品牌 ID,用于区分商户。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_id IS '门店 ID,对应门店维表中的门店主键。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.site_table_id IS '球台/包厢 ID,对应台桌维表主键。 | 来源: site_table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.tenant_member_id IS '商户维度会员 ID,对应会员档案主键;0 表示非会员或散客。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.system_member_id IS '系统级会员 ID,用于跨门店识别同一会员。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_no IS '助教编号/工号,如 “27”;与助教档案中的工号一致。 | 来源: assistantNo';
+COMMENT ON COLUMN dwd_assistant_service_log.nickname IS '助教对外昵称,如“佳怡”“周周”;用于展示,不参与业务逻辑。 | 来源: nickname';
+COMMENT ON COLUMN dwd_assistant_service_log.site_assistant_id IS '门店维度助教 ID,对应助教账号维表主键。 | 来源: site_assistant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.user_id IS '助教对应的系统用户 ID,对应账号体系中的 user_id。 | 来源: user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_team_id IS '助教团队 ID,用于分组统计团队业绩。 | 来源: assistant_team_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.person_org_id IS '助教所属人事组织/部门 ID,如“助教部”;用于组织维度分析。 | 来源: person_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.assistant_level IS '助教等级编码:8=助教管理;10=初级;20=中级;30=高级;用于薪酬/评价分层。 | 来源: assistant_level | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.level_name IS '助教等级名称,与 assistant_level 对应,如“初级”“中级”“高级”“助教管理”。 | 来源: levelName';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_id IS '助教服务课程/技能 ID,应对应课程/技能配置表。 | 来源: skill_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log.skill_name IS '助教服务课程/技能名称,如“基础课”“附加课”。 | 来源: skillName';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_unit_price IS '助教服务标准单价(原价),例如按小时或按节课的标价。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_assistant_service_log.ledger_amount IS '按标准单价计算的应收金额,近似等于 ledger_unit_price×计费时长换算后的金额。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_assistant_service_log.projected_income IS '实际计入门店收入的金额,已经考虑会员权益、券抵扣等后的结果。 | 来源: projected_income';
+COMMENT ON COLUMN dwd_assistant_service_log.coupon_deduct_money IS '由优惠券、团购券等直接抵扣到本次助教服务上的金额;0 表示未使用券。 | 来源: coupon_deduct_money';
+COMMENT ON COLUMN dwd_assistant_service_log.income_seconds IS '计费秒数(用于计算应收收入的时间长度),通常为按分钟取整的秒数。 | 来源: income_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.real_use_seconds IS '实际服务时长(秒),真实消耗的时间,用于分析助教工作量。 | 来源: real_use_seconds';
+COMMENT ON COLUMN dwd_assistant_service_log.add_clock IS '加钟秒数,在原有预约基础上临时增加的服务时间,数值为 60 的倍数。 | 来源: add_clock';
+COMMENT ON COLUMN dwd_assistant_service_log.create_time IS '助教流水记录创建时间,接近下单/结算时间。 | 来源: create_time';
+COMMENT ON COLUMN dwd_assistant_service_log.start_use_time IS '助教实际开始服务时间,通常与 ledger_start_time 一致。 | 来源: start_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.last_use_time IS '助教最后一次服务时间,通常与 ledger_end_time 一致。 | 来源: last_use_time';
+COMMENT ON COLUMN dwd_assistant_service_log.is_delete IS '逻辑删除标志:0 未删除;1 已逻辑删除,用于保留历史数据。 | 来源: is_delete';
+
+-- dwd_assistant_service_log_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_service_log_Ex (
+ assistant_service_id BIGINT,
+ table_name VARCHAR(64),
+ assistant_name VARCHAR(64),
+ ledger_name VARCHAR(128),
+ ledger_group_name VARCHAR(128),
+ ledger_count INTEGER,
+ member_discount_amount NUMERIC(10,2),
+ manual_discount_amount NUMERIC(10,2),
+ service_money NUMERIC(10,2),
+ returns_clock INTEGER,
+ ledger_start_time TIMESTAMPTZ,
+ ledger_end_time TIMESTAMPTZ,
+ ledger_status INTEGER,
+ is_confirm INTEGER,
+ is_single_order INTEGER,
+ is_not_responding INTEGER,
+ is_trash INTEGER,
+ trash_applicant_id BIGINT,
+ trash_applicant_name VARCHAR(64),
+ trash_reason VARCHAR(255),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_org_id BIGINT,
+ skill_grade INTEGER,
+ service_grade INTEGER,
+ composite_grade NUMERIC(5,2),
+ sum_grade NUMERIC(10,2),
+ get_grade_times INTEGER,
+ grade_status INTEGER,
+ composite_grade_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_service_id)
+);
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_service_id IS '助教服务流水主键,系统内唯一标识一次助教服务记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.table_name IS '球台名称,如 “A17”“S1”,与 site_table_id 冗余,用于展示。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.assistant_name IS '助教姓名,如“何海婷”;与助教档案中的真实姓名一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_name IS '助教计费项目名称,如“2-佳怡”等,通常为展示用组合字段。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_group_name IS '助教项目所属的计费分组/套餐分组名称,目前导出数据中为空,未看到实际使用场景。 | 来源: ledger_group_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_count IS '台账计费时长(秒),通常与 real_use_seconds 接近或相等。取income_seconds TEXT';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.member_discount_amount IS '由会员卡折扣产生的优惠金额,当前样本中为 0,但字段语义明确。 | 来源: member_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.manual_discount_amount IS '收银员手动减免金额(人工改价);当前导出数据中为 0。 | 来源: manual_discount_amount';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_money IS '与助教结算的金额或服务成本金额,当前数据全部为 0,具体结算规则未见启用。 | 来源: service_money';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.returns_clock IS '退钟秒数(取消加钟或提前结束退回的时间),当前样本中全部为 0,未见业务使用。 | 来源: returns_clock';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_start_time IS '台账计费起始时间。 | 来源: ledger_start_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_end_time IS '台账计费结束时间,可作为本次服务结束时间。 | 来源: ledger_end_time';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.ledger_status IS '助教流水状态:当前数据为 1,表示正常有效;其他值预留给已作废、未结算等状态。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_confirm IS '确认状态:当前样本为 2,一般含义为 1=待确认,2=已确认/已完成(含义基于字段名和现有值推断)。 | 来源: is_confirm';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_single_order IS '是否单独订单:1 表示助教服务作为单独订单结算;0 表示与其他项目合单结算。当前样本全部为 1。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_not_responding IS '是否存在“未响应/爽约”等异常:0 表示正常;1 表示未响应或爽约(基于字段名推断,当前数据均为 0)。 | 来源: is_not_responding';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.is_trash IS '是否已废除:0 表示正常有效;1 表示已废除,与助教废除记录表(assistant_cancellation_records)对应。 | 来源: is_trash';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_id IS '提出废除申请的员工 ID,用于追溯谁发起了废除操作。 | 来源: trash_applicant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_applicant_name IS '废除申请人姓名,仅用于展示,与 trash_applicant_id 冗余。 | 来源: trash_applicant_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.trash_reason IS '废除原因文案,如“顾客取消”“录入错误”,便于分析异常原因。 | 来源: trash_reason';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_user_id IS '营业员/销售员用户 ID,大多为 0,当前门店未明显使用此维度。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_name IS '营业员/销售员姓名,多数为空字符串。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.salesman_org_id IS '营业员所属组织/部门 ID,多数为 0,尚未看到实际业务使用。 | 来源: salesman_org_id | 角色: 外键';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.skill_grade IS '课程技能评分(整数),当前样本全为 0,评价功能尚未启用。 | 来源: skill_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.service_grade IS '服务态度评分(整数),当前样本全为 0。 | 来源: service_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade IS '综合评分(技能+服务等加权结果),当前样本为 0。 | 来源: composite_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.sum_grade IS '累计评分总和,用于计算平均分,当前样本为 0。 | 来源: sum_grade';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.get_grade_times IS '获得评价的次数,当前样本为 0。 | 来源: get_grade_times';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.grade_status IS '评价状态枚举:当前样本为 1,一般含义为“未评价/正常”,其他状态未见实际值。 | 来源: grade_status';
+COMMENT ON COLUMN dwd_assistant_service_log_Ex.composite_grade_time IS '最近一次综合评分时间或评价更新时间,当前为默认时间 “0001-01-01 00:00:00”。 | 来源: composite_grade_time';
+
+-- dwd_assistant_trash_event
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event (
+ assistant_trash_event_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ table_area_id BIGINT,
+ assistant_no VARCHAR(32),
+ assistant_name VARCHAR(64),
+ charge_minutes_raw INTEGER,
+ abolish_amount NUMERIC(18,2),
+ trash_reason VARCHAR(255),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event.site_id IS '门店 ID。与其他 JSON 中的 siteId / site_id 含义一致。用来关联 dim_site。当前样例全部为同一门店(朗朗桌球),但设计上支持多门店。 | 来源: siteId | 角色: 外键(指向 dim_site)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_id IS '台桌 ID。对应 site_tables_master.json 中的 id。用于定位哪一张球台发生了助教废除,用于后续软关联台费流水、助教流水时的重要条件。 | 来源: tableId | 角色: 外键(指向 dim_table)';
+COMMENT ON COLUMN dwd_assistant_trash_event.table_area_id IS '台桌区域 ID。应与台桌维或区域维中的 area_id 一致,用于按区域统计(A 区/B 区/VIP 包厢等)。 | 来源: tableAreaId | 角色: 外键(潜在指向 dim_table_area)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_no IS '助教编号(工号/序号),如 ''2''、''4''、''27'' 等。与助教档案表 assistant_accounts_master.assistant_no、助教流水中的 assistantNo 一致,用于标识哪位助教。枚举:在门店内是有限编号集合,但并非硬编码含义。 | 来源: assistantOn | 角色: 外键(指向 dim_assistant)';
+COMMENT ON COLUMN dwd_assistant_trash_event.assistant_name IS '助教姓名/昵称,如 “泡芙”“佳怡”等。为冗余展示字段,真实姓名以助教档案为准。当前数据中与档案一致。 | 来源: assistantName';
+COMMENT ON COLUMN dwd_assistant_trash_event.charge_minutes_raw IS '助教被废除前“已计费时长(分钟)”的原始值。单位为分钟。示例:214、3600、10800 等。0 表示尚未发生有效计费就被废除。当前数据中存在异常大值(例如 10800),这一业务含义需结合实际规则理解,但本字段原样保留。枚举:数值型,无固定枚举。 | 来源: pdChargeMinutes';
+COMMENT ON COLUMN dwd_assistant_trash_event.abolish_amount IS '与本次助教废除操作关联的金额,单位元。字面含义为“助教废除金额”。当前样例均为非负数,如 5.83、570.00、0.00 等。正负方向:按照 ODS/JSON 原样保留,暂不在数仓层赋予“收入/支出”的方向含义,后续在 DWS 层按业务规则解释(例如是退还顾客、扣除收益等)。 | 来源: assistantAbolishAmount';
+COMMENT ON COLUMN dwd_assistant_trash_event.trash_reason IS '废除原因的文本说明,例如可以写“顾客临时取消”“误操作”等。当前样例中全部为空字符串,说明前台并未使用该字段。但从结构上看,是一个自由文本字段,不是枚举。 | 来源: trashReason';
+COMMENT ON COLUMN dwd_assistant_trash_event.create_time IS '这条废除记录创建的时间,格式 YYYY-MM-DD HH:MM:SS。代表系统正式记录“废除操作”的时刻,用于和助教服务流水按时间窗口做软关联(结合 site、table、assistant 等条件)。 | 来源: createTime';
+
+-- dwd_assistant_trash_event_Ex
+CREATE TABLE IF NOT EXISTS dwd_assistant_trash_event_Ex (
+ assistant_trash_event_id BIGINT,
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ PRIMARY KEY (assistant_trash_event_id)
+);
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.assistant_trash_event_id IS '助教废除事件主键。与源 JSON 中 id 一一对应,单表内唯一。没有业务含义,只作为技术主键使用。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_name IS '台桌名称/编号,便于直观看报表,如 “C1”“B9”“VIP1”等。文案冗余自台桌维度。枚举:在门店范围内是有限集合,但不是固定编码表。 | 来源: tableName';
+COMMENT ON COLUMN dwd_assistant_trash_event_Ex.table_area_name IS '台桌区域名称(中文),如 “A区”“B区”“C区”“VIP包厢”“补时长”等。展示用文本,具体层级信息由区域维表提供。 | 来源: tableArea';
+
+-- dwd_member_balance_change
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change (
+ balance_change_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ register_site_id BIGINT,
+ tenant_member_id BIGINT,
+ system_member_id BIGINT,
+ tenant_member_card_id BIGINT,
+ card_type_id BIGINT,
+ card_type_name VARCHAR(32),
+ member_name VARCHAR(64),
+ member_mobile VARCHAR(20),
+ balance_before NUMERIC(18,2),
+ change_amount NUMERIC(18,2),
+ balance_after NUMERIC(18,2),
+ from_type INTEGER,
+ payment_method INTEGER,
+ change_time TIMESTAMPTZ,
+ is_delete INTEGER,
+ remark VARCHAR(255),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_id IS '租户/品牌 ID,在整体系统中唯一标识一家商户。当前样本中为同一值。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.site_id IS '本次余额变动发生的门店 ID。通常对应具体门店;样本中:非 0 为“朗朗桌球”,0 代表平台级/虚拟门店场景(如活动抵用券结算)。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.register_site_id IS '办卡门店 ID(卡注册门店)。与 site_id 区分:register_site_id=当初办卡门店,site_id=本次余额变动实际发生门店。当前样本中全部相同。 | 来源: register_site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_id IS '租户维度会员 ID(同一租户内的会员主键),用于关联会员档案。 | 来源: tenant_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.system_member_id IS '系统全局会员 ID(跨租户统一的会员标识)。当前只有一个门店,但结构上允许同一人跨租户共享该 ID。 | 来源: system_member_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.tenant_member_card_id IS '会员卡账户 ID(租户内唯一的一张具体卡,例如某人的储值卡/酒水卡/台费卡/活动抵用券等)。本次余额变动作用于这张卡。 | 来源: tenant_member_card_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_id IS '卡种类型 ID。与 card_type_name 一一对应,用于区分不同卡种(储值卡/活动抵用券/酒水卡/台费卡)。 | 来源: card_type_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change.card_type_name IS '卡种名称(中文):• 储值卡:通用储值卡;• 活动抵用券:活动送券型卡;• 酒水卡:指定用于酒水类消费;• 台费卡:指定用于台费消费。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_member_balance_change.member_name IS '会员姓名/称呼(如“曾丹烨”“葛先生”“胡先生”),主要用于运营、客服和人工识别。 | 来源: memberName';
+COMMENT ON COLUMN dwd_member_balance_change.member_mobile IS '会员手机号(完整号码字符串),是会员识别、营销触达的重要字段。 | 来源: memberMobile';
+COMMENT ON COLUMN dwd_member_balance_change.balance_before IS '本次变动前的卡内余额,单位:元。可为 0、数百、数千等。 | 来源: before';
+COMMENT ON COLUMN dwd_member_balance_change.change_amount IS '本次余额变动金额,单位:元:• 正数:余额增加(充值、赠送、调整加款等);• 负数:余额减少(消费扣款、退款冲减、活动抵扣等)。所有记录严格满足:balance_after = balance_before + change_amount(浮点精度内)。 | 来源: account_data';
+COMMENT ON COLUMN dwd_member_balance_change.balance_after IS '本次变动后的卡内余额,单位:元。由 before + account_data 计算而得,在源数据中已给出。 | 来源: after';
+COMMENT ON COLUMN dwd_member_balance_change.from_type IS '余额变动来源类型枚举(控制业务含义与方向):• 1:日常消费扣款 —— change_amount 为负数,payment_method=0,表示用卡支付消费被扣余额;• 3:充值增加 —— change_amount 为正数,payment_method=4,表示顾客通过外部支付为卡充值(扫码、银行卡等);• 4:调整/赠送增加 —— change_amount 为正数,payment_method=3,通常为后台赠送或手工加款;• 7:充值退款 —— change_amount 为负数,remark=''充值退款'',表示对历史充值做退款,以减少卡内余额方式体现;• 9:活动抵用券相关余额冲减 —— change_amount 为负数,卡种为“活动抵用券”,site_id=0,表示活动券额度被扣回或结算;• 2:其他增加 —— 当前仅 1 条正数样本(+1865.80),具体业务类型不明,但可确定为余额增加类。总体上:1/7/9 为减余额类,2/3/4 为加余额类。 | 来源: from_type';
+COMMENT ON COLUMN dwd_member_balance_change.payment_method IS '支付/变动渠道枚举(与源系统支付方式枚举一致):• 0:内部结算/无外部支付 —— 日常消费扣款、内部扣减、退款冲减等场景,新资金流不在本记录中产生;• 3:赠送/后台调整渠道 —— 与 from_type=4 搭配出现,表示此余额增加不是顾客付钱,而是后台发放或内部调账;• 4:充值外部支付渠道 —— 与 from_type=3 搭配出现,代表顾客通过某外部渠道完成充值(具体是微信/支付宝/银行卡等需要结合支付枚举表进一步映射)。 | 来源: payment_method';
+COMMENT ON COLUMN dwd_member_balance_change.change_time IS '余额变动时间(记录创建时间),格式 YYYY-MM-DD HH:MM:SS。通常紧邻实际交易发生时间,用于按时间线分析资金变动。 | 来源: create_time';
+COMMENT ON COLUMN dwd_member_balance_change.is_delete IS '逻辑删除标记:• 0:正常记录(当前样本全部为 0);• 1:逻辑删除(标记为删除但数据库保留,用于追溯)。分析时通常需要过滤掉 is_delete=1 的记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_member_balance_change.remark IS '余额变动备注信息。当前样本中主要为:• 空字符串:无额外说明;• 充值退款:明确标记该条记录为“充值退款”业务,与 from_type=7 完全对应。后续可能出现其他业务备注。 | 来源: remark';
+
+-- dwd_member_balance_change_EX
+CREATE TABLE IF NOT EXISTS dwd_member_balance_change_EX (
+ balance_change_id BIGINT,
+ pay_site_name VARCHAR(64),
+ register_site_name VARCHAR(64),
+ refund_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ PRIMARY KEY (balance_change_id)
+);
+COMMENT ON COLUMN dwd_member_balance_change_EX.balance_change_id IS '余额变动记录主键 ID,来源于源系统的余额变更流水 ID,唯一标识一条余额变动事件。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.pay_site_name IS '余额变动发生门店名称,对应 site_id 的中文名。示例:朗朗桌球;当 site_id = 0 时通常为空字符串。纯展示冗余。 | 来源: paySiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.register_site_name IS '办卡门店名称,对应 register_site_id 的中文名。当前样本全部为 朗朗桌球,属于冗余展示。 | 来源: registerSiteName';
+COMMENT ON COLUMN dwd_member_balance_change_EX.refund_amount IS '退款金额字段。在当前样本数据中全部为 0.00,推测用于区分“退回卡内余额”和“原路退回”等更细的退款模式,但目前未启用。 | 来源: refund_amount';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_id IS '操作员 ID,执行本次余额变动操作的员工账号主键。可关联员工/账号维度。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_member_balance_change_EX.operator_name IS '操作员名称及职位说明,例如:收银员:郑丽珊、店长:谢晓洪 等,是对 operator_id 的可读冗余。 | 来源: operator_name';
+
+-- dwd_groupbuy_redemption
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption (
+ redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ table_id BIGINT,
+ tenant_table_area_id BIGINT,
+ table_charge_seconds INTEGER,
+ order_trade_no BIGINT,
+ order_settle_id BIGINT,
+ order_coupon_id BIGINT,
+ coupon_origin_id BIGINT,
+ promotion_activity_id BIGINT,
+ promotion_coupon_id BIGINT,
+ order_coupon_channel INTEGER,
+ ledger_unit_price NUMERIC(18,2),
+ ledger_count INTEGER,
+ ledger_amount NUMERIC(18,2),
+ coupon_money NUMERIC(18,2),
+ promotion_seconds INTEGER,
+ coupon_code VARCHAR(64),
+ is_single_order INTEGER,
+ is_delete INTEGER,
+ ledger_name VARCHAR(128),
+ create_time TIMESTAMPTZ,
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_id IS '租户/品牌 ID。与其他表统一的租户标识,用于品牌维度聚合。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.site_id IS '门店 ID。与门店维度及其他业务事实中的 site_id 一致。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_id IS '球台 ID。与台桌维度表中的 id 对应,用于确定具体哪一张球台。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.tenant_table_area_id IS '租户级台区组合 ID。与团购套餐定义中的 tenant_table_area_id_list 元素对应,表示该券实际使用时所在的台区组合。用于校验券的适用台区是否匹配实际台桌。 | 来源: tenant_table_area_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.table_charge_seconds IS '本次结算中该球台总计计费的秒数(整台计费时间)。当台上除了券覆盖时长之外还有额外计费时间时,该值会大于券核销时长。 | 来源: table_charge_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_trade_no IS '订单交易号。与台费流水、商品销售、助教服务、小票详情等表的 order_trade_no 一致,用于将同一笔结账中的所有明细串联起来。 | 来源: order_trade_no | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_settle_id IS '结算单 ID。与结账记录和小票详情中的结算主键对应,用于从团购券核销记录跳转到整单结算。 | 来源: order_settle_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_id IS '订单中的“券使用记录 ID”。与平台或内部券核销表中的主键一致,用于在订单内部定位这条券使用记录。当前与 coupon_origin_id 数值相等。 | 来源: order_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_origin_id IS '上游系统或第三方平台中该券记录的主键 ID。可在平台验券记录中查到券的来源平台、原订单等。当前与 order_coupon_id 数值一致,但语义是“券来源 ID”。 | 来源: coupon_origin_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_activity_id IS '促销活动 ID。每条记录对应一个活动主键,用于识别券所属的促销活动或团购活动。 | 来源: promotion_activity_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_coupon_id IS '团购套餐定义 ID。与 group_buy_packages.json 中的 id 一一对应,表示当前使用的是哪一种团购套餐(例如某款“一小时套餐”“两小时套餐”)。 | 来源: promotion_coupon_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.order_coupon_channel IS '券渠道类型枚举。观测值:1(大量记录)、2(少量记录)。用于区分券的来源渠道,例如不同团购平台或内部券。具体数值与渠道名称的映射由业务配置决定。 | 来源: order_coupon_channel | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_unit_price IS '本次券在台费侧对应的标准单价,单位元/小时。典型值如 29.9、39.9、59.9、69.9 等。与门店台费计费规则中的单价相对应,用于计算券对应的金额。 | 来源: ledger_unit_price';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_count IS '本次券实际核销的计费秒数。大部分记录等于 promotion_seconds,少数略小于标准时长,表示这张券只覆盖了本次台费的一部分时长。 | 来源: ledger_count';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_amount IS '本次团购券实际冲抵台费的金额。大部分记录中该值与 coupon_money 相等,少数存在小数差异,来源于按单价与秒数换算的结果。 | 来源: ledger_amount';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_money IS '本次核销时,团购券在门店侧对应的金额额度(可抵扣金额)。同一种 promotion_coupon_id 下,该值固定,例如某套餐固定为 48.00 元、某套餐固定为 96.00 元等。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption.promotion_seconds IS '团购套餐定义的标准时长权益,单位秒。观测枚举值为 3600、7200、14400,分别对应 1 小时、2 小时、4 小时。与团购套餐定义表中的 duration 字段一致。 | 来源: promotion_seconds';
+COMMENT ON COLUMN dwd_groupbuy_redemption.coupon_code IS '团购券券码字符串。每条记录一个唯一券码,例如“0107892475999”。用于与平台验券记录、券购买记录等做一一对应,追踪券的全生命周期。 | 来源: coupon_code | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_single_order IS '是否作为单独订单行。观测值:1 为主,表示以独立条目方式结算;0 为个别记录,表示嵌入某种组合结算结构。具体业务含义依赖上层订单结构设计。 | 来源: is_single_order';
+COMMENT ON COLUMN dwd_groupbuy_redemption.is_delete IS '逻辑删除标记。0 表示正常记录,1 表示逻辑删除但数据仍保留用于追溯。当前样本全部为 0,用于过滤有效记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_groupbuy_redemption.ledger_name IS '团购项目记账名称,如“全天A区中八一小时”“B区桌球一小时”“中八、斯诺克包厢两小时”等。通常与团购套餐名称相近,用于报表展示和套餐维度分析。 | 来源: ledger_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption.create_time IS '本条团购券核销流水的创建时间,通常即核销时间,格式为“YYYY-MM-DD HH:MM:SS”。用于时间维度分析和数据分区。 | 来源: create_time';
+
+-- dwd_groupbuy_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_groupbuy_redemption_Ex (
+ redemption_id BIGINT,
+ site_name VARCHAR(64),
+ table_name VARCHAR(64),
+ table_area_name VARCHAR(64),
+ order_pay_id BIGINT,
+ goods_option_price NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ table_service_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_service_promotion_money NUMERIC(18,2),
+ reward_promotion_money NUMERIC(18,2),
+ recharge_promotion_money NUMERIC(18,2),
+ offer_type INTEGER,
+ ledger_status INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(64),
+ salesman_user_id BIGINT,
+ salesman_name VARCHAR(64),
+ salesman_role_id BIGINT,
+ salesman_org_id BIGINT,
+ ledger_group_name VARCHAR(128),
+ PRIMARY KEY (redemption_id)
+);
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.redemption_id IS '团购券核销流水主键。一条记录代表一次团购券使用在某次台费上的一条核销明细。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.site_name IS '门店名称。当前样本全部为同一门店,仅作冗余展示。 | 来源: siteName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_name IS '球台名称或台号。如 A7、A11、B1 等。用于业务报表展示与人工识别。 | 来源: tableName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_area_name IS '台区名称。观测枚举值包括 A区、B区、斯诺克区、麻将房。实际取值随门店台区配置变化。 | 来源: tableAreaName';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.order_pay_id IS '支付流水 ID。部分记录为 0,表示未在当前导出范围内关联到具体支付记录。真实含义为“指向支付记录表中的支付流水”。 | 来源: order_pay_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_option_price IS '商品规格价格,用于商品类促销分摊时使用。当前在团购券核销场景中全部为 0,仅作为结构预留。 | 来源: goodsOptionPrice';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.goods_promotion_money IS '本次券使用中分摊到“商品”部分的促销金额。当前所有记录为 0,说明本门店的团购券未用于商品抵扣。 | 来源: goods_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.table_service_promotion_money IS '本次券使用中分摊到“台费服务费”部分的促销金额。当前样本全部为 0,结构上用于支持更细粒度的费用拆分。 | 来源: table_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_promotion_money IS '本次券使用中分摊到“助教服务”的促销金额。当前全部为 0,说明团购券尚未用于助教服务的抵扣。 | 来源: assistant_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.assistant_service_promotion_money IS '进一步细分助教服务对应的促销金额。当前为 0,仅预留结构以支持复杂场景。 | 来源: assistant_service_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.reward_promotion_money IS '本次促销中属于“奖励金、积分”等来源的促销金额分摊。当前为 0,预留用于积分或奖励金同时参与活动时的金额拆分。 | 来源: reward_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.recharge_promotion_money IS '来自“充值赠送”等储值优惠的促销金额分摊。当前为 0,预留用于将来区分“券优惠”和“充值赠送优惠”的场景。 | 来源: recharge_promotion_money';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.offer_type IS '优惠类型枚举。当前样本值全部为 1,表示本门店使用的团购券均为同一类型(例如“套餐券”)。其他取值可能对应满减、折扣、代金券等优惠类型,在本数据中未出现。 | 来源: offer_type';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_status IS '流水状态。观测值全部为 1。常规含义为:1 表示正常有效记录;其他值预留用于表示作废、撤销、未生效等状态。当前导出仅包含正常状态记录。 | 来源: ledger_status';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_id IS '执行本次券核销操作的操作员 ID。可与员工维度表对接,用于分析不同操作员的核销行为与绩效。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.operator_name IS '操作员名称及角色说明,例如“收银员:郑丽珊”。与 operator_id 冗余,对报表展示友好,但不参与模型关联。 | 来源: operator_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_user_id IS '营业员用户 ID。当前全部为 0,表示本门店在团购券场景未单独记录营业员信息。 | 来源: salesman_user_id | 角色: 外键';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_name IS '营业员姓名。当前为空字符串。结构上用于记录拉单或促销的业务员信息。 | 来源: salesman_name';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_role_id IS '营业员角色 ID。当前为 0,预留用于标识营业员在组织中的角色类型。 | 来源: salesman_role_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.salesman_org_id IS '营业员所属组织 ID。来源字段为 sales_man_org_id,DWD 层统一命名为 salesman_org_id。当前为 0,用于将来对接组织架构维度。 | 来源: sales_man_org_id';
+COMMENT ON COLUMN dwd_groupbuy_redemption_Ex.ledger_group_name IS '团购项目的记账分组名称。当前全部为空,预留给将来按团购项目大类分组(例如“团购台费”“团购包厢”)使用。 | 来源: ledger_group_name';
+
+-- dwd_platform_coupon_redemption
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption (
+ platform_coupon_redemption_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ coupon_code VARCHAR(64),
+ coupon_channel INTEGER,
+ coupon_name VARCHAR(200),
+ sale_price NUMERIC(10,2),
+ coupon_money NUMERIC(10,2),
+ coupon_free_time INTEGER,
+ channel_deal_id BIGINT,
+ deal_id BIGINT,
+ group_package_id BIGINT,
+ site_order_id BIGINT,
+ table_id BIGINT,
+ certificate_id VARCHAR(64),
+ verify_id VARCHAR(64),
+ use_status INTEGER,
+ is_delete INTEGER,
+ create_time TIMESTAMPTZ,
+ consume_time TIMESTAMPTZ,
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.tenant_id IS '租户 ID,品牌级别标识。例如整套系统中的“朗朗桌球”品牌。与其他表的 tenant_id 一致,用于划分租户数据域。 | 来源: tenant_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于区分不同门店。siteProfile.id 与此字段相同,本表不再冗余门店快照。 | 来源: site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_code IS '第三方团购券券码,顾客出示的核销码。当前样本中全表唯一,可视为业务自然主键,用于验券、对账、查询。 | 来源: coupon_code';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_channel IS '券来源渠道枚举,表示第三方平台渠道编号。观测值:1,2。具体含义需结合系统配置,一般可理解为:1 表示平台渠道 1(主平台),2 表示平台渠道 2(其他入口或子平台)。 | 来源: coupon_channel';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_name IS '第三方团购券产品名称,例如“【全天可用】中八桌球一小时(A区)”“1小时中八台球【11月特惠】(A区)”等。用于报表展示和区分不同团购产品。 | 来源: coupon_name';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.sale_price IS '顾客在第三方平台实际支付的团购售价,例如 11.11、29.90、39.90 等。始终小于 coupon_money,体现“折后价”。 | 来源: sale_price';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_money IS '券面值或套餐价值,即系统认为该券可抵扣的金额,例如 48.00、58.00、68.00、96.00、116.00、288.00。与 coupon_name 有固定对应关系。 | 来源: coupon_money';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.coupon_free_time IS '券附带的赠送时长,单位:秒。当前样本全部为 0,表示无独立赠送时长。若未来有赠送时间型券,则该字段存储赠送的秒数。 | 来源: coupon_free_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.channel_deal_id IS '渠道侧团购商品 ID(第三方平台 dealId)。值域有限(约 9 个值),与 coupon_name 一一对应。用于对接第三方接口和按平台商品维度统计。 | 来源: channel_deal_id | 角色: - 或 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.deal_id IS '平台/系统侧团购商品 ID。多数记录为非 0 整数,也有部分为 0。与 coupon_name 存在稳定对应关系,0 表示内部未配置或未同步。未来可作为内部团购商品维度外键。 | 来源: deal_id | 角色: 外键(预留)';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.group_package_id IS '内部“团购套餐”定义表主键 ID。当前样本中全部为 0,表示平台券尚未映射到自有团购套餐;从设计上是预留的外键字段。 | 来源: group_package_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.site_order_id IS '门店内部订单 ID。本次平台券核销所挂靠的店内订单号。用于与结账记录、台费流水、商品销售等事实表通过订单维度关联。 | 来源: site_order_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.table_id IS '使用团购券的球台 ID。与 dim_site_table.table_id 对应,用于统计每张球台的第三方平台引流情况。 | 来源: table_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.certificate_id IS '第三方平台侧券实例 ID(凭证 ID),通常为 16–19 位数字字符串。用于与外部平台对账与查询核销结果。存在重复值,不能单独作为唯一键。 | 来源: certificate_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.verify_id IS '第三方平台核销记录 ID。大部分记录为空,少量有值。存在时可用于精确反查平台侧核销记录。 | 来源: verify_id';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.use_status IS '券使用状态枚举。观测值:1、2。1 表示已使用/已核销(正常消耗);2 表示已退款/已撤销或使用后反冲的状态。是判断券生命周期状态的核心字段。 | 来源: use_status';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.is_delete IS '逻辑删除标志。0 表示未删除;1 表示已逻辑删除。与 use_status 独立:即便业务状态异常(如 use_status=2),也可能 is_delete 仍为 0 以保留记录。 | 来源: is_delete';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.create_time IS '系统记录创建时间,即核销记录写入本系统的时间。格式为 YYYY-MM-DD HH:MM:SS。通常与 consume_time 相差约 1 秒。 | 来源: create_time';
+COMMENT ON COLUMN dwd_platform_coupon_redemption.consume_time IS '券被核销/使用的业务时间,代表实际团购券使用发生的时间点。后续按核销日期统计核销量时以该字段为准。 | 来源: consume_time';
+
+-- dwd_platform_coupon_redemption_Ex
+CREATE TABLE IF NOT EXISTS dwd_platform_coupon_redemption_Ex (
+ platform_coupon_redemption_id BIGINT,
+ coupon_cover VARCHAR(255),
+ coupon_remark VARCHAR(255),
+ groupon_type INTEGER,
+ operator_id BIGINT,
+ operator_name VARCHAR(50),
+ PRIMARY KEY (platform_coupon_redemption_id)
+);
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.platform_coupon_redemption_id IS '平台券核销记录在本系统内的主键 ID。长整型分布式 ID,用于唯一标识本次核销流水。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_cover IS '券封面图片地址 URL,用于前端展示团购券图片。对经营分析和结算逻辑无影响。 | 来源: coupon_cover';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.coupon_remark IS '券描述或备注信息,用于展示券规则、说明文字。未参与计算和关联逻辑。 | 来源: coupon_remark';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.groupon_type IS '团购券类型枚举。当前样本全部为 1。推断含义:1 表示标准团购券,其他值预留为次卡、套餐券、权益券等类型。 | 来源: groupon_type';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_id IS '执行验券操作的员工/收银员账号 ID。当前样本中多数为同一值。可与员工/账号维度表关联。 | 来源: operator_id | 角色: 外键';
+COMMENT ON COLUMN dwd_platform_coupon_redemption_Ex.operator_name IS '操作员姓名或显示名,例如“收银员:郑丽珊”。是 operator_id 的冗余展示字段,用于报表展示。 | 来源: operator_name';
+
+-- dwd_recharge_order
+CREATE TABLE IF NOT EXISTS dwd_recharge_order (
+ recharge_order_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ member_id BIGINT,
+ member_name_snapshot TEXT,
+ member_phone_snapshot TEXT,
+ tenant_member_card_id BIGINT,
+ member_card_type_name TEXT,
+ settle_relate_id BIGINT,
+ settle_type INTEGER,
+ settle_name TEXT,
+ is_first INTEGER,
+ pay_amount NUMERIC(18,2),
+ refund_amount NUMERIC(18,2),
+ point_amount NUMERIC(18,2),
+ cash_amount NUMERIC(18,2),
+ payment_method INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order.tenant_id IS '租户/品牌 ID;与其他 JSON 中 tenantId 含义一致。 | 来源: tenantId | 角色: 外键(dim_tenant)';
+COMMENT ON COLUMN dwd_recharge_order.site_id IS '门店 ID;与 siteProfile.id 一致,用于关联门店维度。 | 来源: siteId | 角色: 外键(dim_site)';
+COMMENT ON COLUMN dwd_recharge_order.member_id IS '会员 ID;对应会员档案中的 tenantMemberInfos.id。标识给哪个会员充值。 | 来源: memberId | 角色: 外键(dim_member)';
+COMMENT ON COLUMN dwd_recharge_order.member_name_snapshot IS '会员姓名/昵称快照,可能是名称或手机号字符串。 | 来源: memberName';
+COMMENT ON COLUMN dwd_recharge_order.member_phone_snapshot IS '会员手机号快照。 | 来源: memberPhone';
+COMMENT ON COLUMN dwd_recharge_order.tenant_member_card_id IS '会员卡实例 ID(某张具体卡);可关联 dim_member_card_account。 | 来源: tenantMemberCardId | 角色: 外键(dim_member_card_account)';
+COMMENT ON COLUMN dwd_recharge_order.member_card_type_name IS '会员卡类型名称;当前样例主要有:“储值卡”、“月卡”。 | 来源: memberCardTypeName';
+COMMENT ON COLUMN dwd_recharge_order.settle_relate_id IS '结算关联 ID;用于与支付记录等跨表关联(类似业务单 ID)。 | 来源: settleRelateId | 角色: 外键(与支付/结算域软关联)';
+COMMENT ON COLUMN dwd_recharge_order.settle_type IS '结算类型枚举:5=“充值订单”(正常充值);7=“充值撤销”(冲销记录)。 | 来源: settleType';
+COMMENT ON COLUMN dwd_recharge_order.settle_name IS '结算类型名称:"充值订单"、"充值撤销";前端展示用。 | 来源: settleName';
+COMMENT ON COLUMN dwd_recharge_order.is_first IS '是否首充标记。取值:1 或 2。理论含义类似“是否首充”,但 1/2 的精确定义需系统字典确认。 | 来源: isFirst';
+COMMENT ON COLUMN dwd_recharge_order.pay_amount IS '本条记录的充值金额(可为正/负):正数=实际充值金额;负数=撤销流水金额(settleType=7)。 | 来源: payAmount';
+COMMENT ON COLUMN dwd_recharge_order.refund_amount IS '对该充值订单的退款金额(通常为正数);原始充值单上为已退款金额,对应会有一条负数的“充值撤销”记录。 | 来源: refundAmount';
+COMMENT ON COLUMN dwd_recharge_order.point_amount IS '计入会员账户的储值/积分金额;多数情况下等于 pay_amount 的绝对值;撤销记录一般为 0。 | 来源: pointAmount';
+COMMENT ON COLUMN dwd_recharge_order.cash_amount IS '现金收款金额;样本中少数为 3000/5000,其余为 0。 | 来源: cashAmount';
+COMMENT ON COLUMN dwd_recharge_order.payment_method IS '支付方式编码。样本取值:1、2、4;具体对应渠道(现金/微信/支付宝/银行卡等)需系统“支付方式字典”确认。 | 来源: paymentMethod';
+COMMENT ON COLUMN dwd_recharge_order.create_time IS '充值记录创建时间(收银完成时间);用于时间分区、统计。 | 来源: createTime';
+COMMENT ON COLUMN dwd_recharge_order.pay_time IS '支付完成时间;通常与 create_time 接近或相同。 | 来源: payTime';
+
+-- dwd_recharge_order_Ex
+CREATE TABLE IF NOT EXISTS dwd_recharge_order_Ex (
+ recharge_order_id BIGINT,
+ site_name_snapshot TEXT,
+ settle_status INTEGER,
+ is_bind_member BOOLEAN,
+ is_activity BOOLEAN,
+ is_use_coupon BOOLEAN,
+ is_use_discount BOOLEAN,
+ can_be_revoked BOOLEAN,
+ online_amount NUMERIC(18,2),
+ balance_amount NUMERIC(18,2),
+ card_amount NUMERIC(18,2),
+ coupon_amount NUMERIC(18,2),
+ recharge_card_amount NUMERIC(18,2),
+ gift_card_amount NUMERIC(18,2),
+ prepay_money NUMERIC(18,2),
+ consume_money NUMERIC(18,2),
+ goods_money NUMERIC(18,2),
+ real_goods_money NUMERIC(18,2),
+ table_charge_money NUMERIC(18,2),
+ service_money NUMERIC(18,2),
+ activity_discount NUMERIC(18,2),
+ all_coupon_discount NUMERIC(18,2),
+ goods_promotion_money NUMERIC(18,2),
+ assistant_promotion_money NUMERIC(18,2),
+ assistant_pd_money NUMERIC(18,2),
+ assistant_cx_money NUMERIC(18,2),
+ assistant_manual_discount NUMERIC(18,2),
+ coupon_sale_amount NUMERIC(18,2),
+ member_discount_amount NUMERIC(18,2),
+ point_discount_price NUMERIC(18,2),
+ point_discount_cost NUMERIC(18,2),
+ adjust_amount NUMERIC(18,2),
+ rounding_amount NUMERIC(18,2),
+ operator_id BIGINT,
+ operator_name_snapshot TEXT,
+ salesman_user_id BIGINT,
+ salesman_name TEXT,
+ order_remark TEXT,
+ table_id INTEGER,
+ serial_number INTEGER,
+ revoke_order_id BIGINT,
+ revoke_order_name TEXT,
+ revoke_time TIMESTAMPTZ,
+ PRIMARY KEY (recharge_order_id)
+);
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_order_id IS '充值结算记录主键;唯一标识一条充值/撤销记录。 | 来源: id | 角色: 主键';
+COMMENT ON COLUMN dwd_recharge_order_Ex.site_name_snapshot IS '门店名称快照,如“朗朗桌球”;仅用于展示,门店改名后本字段不变。 | 来源: siteName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.settle_status IS '结算状态;当前数据全部为 2,推测 2=已完成。其它状态未出现在样本中。 | 来源: settleStatus';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_bind_member IS '是否绑定为会员/其他绑定标记;当前所有记录为 False,而又都有 memberId,实际业务含义不清。 | 来源: isBindMember';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_activity IS '是否关联营销活动;当前全部为 False,表示样本周期内充值未绑定活动。 | 来源: isActivity';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_coupon IS '本次充值是否使用优惠券;当前样本全部为 False。结构上预留“充值用券”的能力。 | 来源: isUseCoupon';
+COMMENT ON COLUMN dwd_recharge_order_Ex.is_use_discount IS '是否使用折扣(如充值折扣);样本中全为 False。 | 来源: isUseDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.can_be_revoked IS '当前记录是否仍可撤销;样本中全为 False(导出时均不可撤销)。 | 来源: canBeRevoked';
+COMMENT ON COLUMN dwd_recharge_order_Ex.online_amount IS '线上支付金额(如微信、支付宝等);当前样本为 0,但字段为支付渠道拆分预留。 | 来源: onlineAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.balance_amount IS '从账户余额中支付的金额;充值场景通常为 0(用余额充值没有实际意义)。 | 来源: balanceAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.card_amount IS '从其他储值卡或某种卡余额支付的金额;当前样本全为 0。 | 来源: cardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_amount IS '使用券直接支付的金额(如储值券);当前样本为 0。 | 来源: couponAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.recharge_card_amount IS '充值到卡上的金额(与 point_amount 区分不同资金属性);样本为 0,结构预留。 | 来源: rechargeCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.gift_card_amount IS '赠送卡金额(如买 1000 送 100 的赠送部分);当前样本为 0。 | 来源: giftCardAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.prepay_money IS '预付款金额(订金);当前样本为 0,充值未启用此场景。 | 来源: prepayMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.consume_money IS '消费总金额;在充值文件中全部为 0,实际用于消费场景(台费/商品)的结算模型复用字段。 | 来源: consumeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_money IS '商品消费金额(充值记录中为 0)。 | 来源: goodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.real_goods_money IS '实际应计商品金额(扣除折扣后);充值记录中为 0。 | 来源: realGoodsMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_charge_money IS '台费金额;充值记录中为 0,来自通用结算模型。 | 来源: tableChargeMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.service_money IS '服务项目金额(如助教、其他服务);充值中为 0。 | 来源: serviceMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.activity_discount IS '营销活动折扣金额;当前样本为 0。 | 来源: activityDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.all_coupon_discount IS '各类优惠券、团购券综合折扣金额;样本为 0。 | 来源: allCouponDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.goods_promotion_money IS '商品促销优惠金额;样本为 0。 | 来源: goodsPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_promotion_money IS '助教相关促销优惠金额;样本为 0。 | 来源: assistantPromotionMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_pd_money IS '助教配单金额/相关费用;样本为 0。 | 来源: assistantPdMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_cx_money IS '助教冲销/促销相关金额;样本为 0。 | 来源: assistantCxMoney';
+COMMENT ON COLUMN dwd_recharge_order_Ex.assistant_manual_discount IS '助教手工减免金额;样本为 0。 | 来源: assistantManualDiscount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.coupon_sale_amount IS '券/套餐销售金额(售卖券时使用);充值场景中为 0。 | 来源: couponSaleAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.member_discount_amount IS '因会员折扣产生的优惠金额;在充值样本中为 0。 | 来源: memberDiscountAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_price IS '积分抵扣产生的价差(价格部分);样本为 0。 | 来源: pointDiscountPrice';
+COMMENT ON COLUMN dwd_recharge_order_Ex.point_discount_cost IS '积分抵扣对应的成本金额;样本为 0。 | 来源: pointDiscountCost';
+COMMENT ON COLUMN dwd_recharge_order_Ex.adjust_amount IS '手工调整金额(非抹零);样本为 0。 | 来源: adjustAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.rounding_amount IS '抹零金额(四舍五入产生的差额);样本为 0。 | 来源: roundingAmount';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_id IS '操作该笔充值的收银员/员工 ID。 | 来源: operatorId | 角色: 外键(将来可关联 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.operator_name_snapshot IS '操作员姓名快照,便于直接阅读;与 operator_id 对应。 | 来源: operatorName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_user_id IS '营业员用户 ID;当前样本全部为 0。 | 来源: salesManUserId | 角色: 外键(潜在 dim_staff)';
+COMMENT ON COLUMN dwd_recharge_order_Ex.salesman_name IS '营业员/销售员姓名;样本为空字符串。 | 来源: salesManName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.order_remark IS '充值订单备注,如手工说明;当前样本为空。 | 来源: orderRemark';
+COMMENT ON COLUMN dwd_recharge_order_Ex.table_id IS '台桌 ID;充值场景下全部是 0,表示该订单不挂具体球台。 | 来源: tableId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.serial_number IS '流水/小票序号;当前样本全部为 0,本门店未启用。 | 来源: serialNumber';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_id IS '撤销相关订单 ID(被撤销原单或撤销单指针);样本中存在值但逻辑未完全启用。 | 来源: revokeOrderId';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_order_name IS '撤销单名称/说明;样本全为空。 | 来源: revokeOrderName';
+COMMENT ON COLUMN dwd_recharge_order_Ex.revoke_time IS '撤销时间;当前样本为空,撤销信息主要通过负数流水与 refund_amount 表达。 | 来源: revokeTime';
+
+-- dwd_payment
+CREATE TABLE IF NOT EXISTS dwd_payment (
+ payment_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ payment_method INTEGER,
+ online_pay_channel INTEGER,
+ create_time TIMESTAMPTZ,
+ pay_time TIMESTAMPTZ,
+ pay_date DATE,
+ PRIMARY KEY (payment_id)
+);
+COMMENT ON COLUMN dwd_payment.payment_id IS '支付流水主键ID。与源系统 id 一致。每条支付流水唯一标识一条支付行为(包括金额为 0 的记录)。 | 来源: payment_transactions.id | 角色: 主键';
+COMMENT ON COLUMN dwd_payment.site_id IS '门店ID。当前样本中全部为同一门店 2790685415443269。在数仓中外键关联 dim_site.site_id。 | 来源: payment_transactions.site_id | 角色: 外键';
+COMMENT ON COLUMN dwd_payment.relate_type IS '业务关联类型枚举,用来区分这条支付流水对应哪一类业务单据:• 2:结账单支付,对应结账记录 settlement_records 中的结账单;• 5:会员卡充值/账户变动类支付,对应会员余额/充值业务单号,在会员余额变更或充值结算中复用;• 1:其他业务类型,目前样本中仅有 1 条记录,具体业务含义待业务侧补充。 | 来源: payment_transactions.relate_type | 角色: −';
+COMMENT ON COLUMN dwd_payment.relate_id IS '关联业务记录ID,配合 relate_type 使用,是一个“多态外键”:• 当 relate_type = 2 时:relate_id = settlement_records.settleList.id(结账记录主键,对应 dwd_settlement_head_di.order_settle_id);• 当 relate_type = 5 时:relate_id = 会员卡余额变动/充值业务单号,在会员余额变更流水中同名字段使用;• 当 relate_type = 1 时:关联具体业务尚未确认,仅可视为预留类型。 | 来源: payment_transactions.relate_id | 角色: 外键(多业务类型)';
+COMMENT ON COLUMN dwd_payment.pay_amount IS '本次支付金额,单位元。为收入类字段,当前样本全部为非负数:• 正数:实际通过该支付方式收取的金额;• 0:仍生成支付流水,但实收金额为 0(例如整单由会员优惠、团购券、余额等抵扣),当前样本中有 140 条记录金额为 0。 | 来源: payment_transactions.pay_amount | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_status IS '支付状态枚举。当前样本中仅出现:• 2:支付成功。其它可能的状态(未支付、支付中、失败、已退款等)在本次导出中未出现,需以后按系统支付状态配置补充。由于本 JSON 仅导出成功记录,可以视作“成功支付流水视图”。 | 来源: payment_transactions.pay_status | 角色: −';
+COMMENT ON COLUMN dwd_payment.payment_method IS '支付方式枚举。当前样本中出现的取值:• 2:共 140 条记录;• 4:共 60 条记录。具体取值与“支付方式配置表”对应,例如可能代表现金、扫码支付、银行卡等。由于配置表未导出,在数仓中应作为枚举码字段,通过后续 dim_payment_method 进行解码。不要在数仓层擅自写死“2=微信、4=支付宝”等含义。 | 来源: payment_transactions.payment_method | 角色: 外键(预期关联支付方式维度)';
+COMMENT ON COLUMN dwd_payment.online_pay_channel IS '线上支付通道枚举。用于进一步细分线上渠道,例如:• 0:无线上通道/线下,或未区分具体线上通道(当前样本全部为 0);• 1:微信(推测,未在样本中出现);• 2:支付宝(推测,未在样本中出现)。目前门店在当前时间段内尚未使用该字段进行实际区分,业务含义需结合正式配置确认。 | 来源: payment_transactions.online_pay_channel | 角色: −';
+COMMENT ON COLUMN dwd_payment.create_time IS '支付流水创建时间,格式 YYYY-MM-DD HH:MM:SS。通常是发起支付请求的时间。当前样本中 create_time 与 pay_time 多数相同,但模型上允许两者不同(例如异步支付)。 | 来源: payment_transactions.create_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_time IS '支付完成时间(支付成功时间戳),格式 YYYY-MM-DD HH:MM:SS。用于统计资金实际入账时间,以及与结账时间进行对齐分析。 | 来源: payment_transactions.pay_time | 角色: −';
+COMMENT ON COLUMN dwd_payment.pay_date IS '支付日期分区字段,从 pay_time 截取 YYYY-MM-DD 得到。例如 pay_time = ''2025-11-09 23:35:57'' 时,pay_date = ''2025-11-09''。用于 DWD 表按天分区和日粒度汇总。 | 来源: 由 payment_transactions.pay_time 派生 | 角色: −';
+
+-- dwd_refund
+ CREATE TABLE IF NOT EXISTS dwd_refund (
+ refund_id BIGINT,
+ tenant_id BIGINT,
+ site_id BIGINT,
+ relate_type INTEGER,
+ relate_id BIGINT,
+ pay_amount NUMERIC(18,2),
+ channel_fee NUMERIC(18,2),
+ pay_time TIMESTAMPTZ,
+ create_time TIMESTAMPTZ,
+ payment_method INTEGER,
+ member_id BIGINT,
+ member_card_id BIGINT,
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型) | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund.tenant_id IS '租户/品牌 ID,标识所属商户。与其他表中的 tenant_id 一致。 | 来源: tenant_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.site_id IS '门店 ID。与门店维度 dim_site.site_id 对应,用于分门店分析。 | 来源: site_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.relate_type IS '业务类型枚举,指示本退款对应哪类业务主单:当前样本值 {2, 5}:2=消费/结账类业务;5=充值/储值类业务(具体定义以业务字典为准)。与 relate_id 组合使用。 | 来源: relate_type';
+ COMMENT ON COLUMN dwd_refund.relate_id IS '关联的业务主键 ID,含义依赖 relate_type:relate_type=2 时通常指结账主单 ID;relate_type=5 时通常指充值/储值业务单 ID。同一个 relate_id 可能有多笔退款(分批退款)。 | 来源: relate_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.pay_amount IS '本次退款的资金金额,统一为负数。绝对值即退款金额,例如 -5000.00 表示退款 5000 元。 | 来源: pay_amount';
+ COMMENT ON COLUMN dwd_refund.channel_fee IS '第三方支付渠道对本次退款收取的手续费。当前样本为 0.00,用于通道成本核算。 | 来源: channel_fee';
+ COMMENT ON COLUMN dwd_refund.pay_time IS '退款在支付渠道/系统中发生的时间(退款完成时间),用于对账及按时间统计。 | 来源: pay_time';
+ COMMENT ON COLUMN dwd_refund.create_time IS '本条退款流水在系统内创建时间,用于区分记录生成时间与渠道时间。 | 来源: create_time';
+ COMMENT ON COLUMN dwd_refund.payment_method IS '支付方式枚举,指本次退款对应的原支付方式(如通道)。样本出现值 4,支付记录中有 {2,4},具体含义需参照支付方式配置表。 | 来源: payment_method';
+ COMMENT ON COLUMN dwd_refund.member_id IS '关联的会员 ID,对应会员档案表主键。样本为 0,表示未绑定会员。 | 来源: member_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund.member_card_id IS '关联的会员卡账户 ID,对应会员卡账户/储值卡维度主键。样本为 0,当前没有“退到会员卡”的记录。 | 来源: member_card_id | 角色: 外键';
+
+
+ CREATE TABLE IF NOT EXISTS dwd_refund_Ex (
+ refund_id BIGINT,
+ tenant_name VARCHAR(64),
+ pay_sn BIGINT,
+ refund_amount NUMERIC(18,2),
+ round_amount NUMERIC(18,2),
+ balance_frozen_amount NUMERIC(18,2),
+ card_frozen_amount NUMERIC(18,2),
+ pay_status INTEGER,
+ action_type INTEGER,
+ is_revoke INTEGER,
+ is_delete INTEGER,
+ check_status INTEGER,
+ online_pay_channel INTEGER,
+ online_pay_type INTEGER,
+ pay_terminal INTEGER,
+ pay_config_id INTEGER,
+ cashier_point_id INTEGER,
+ operator_id BIGINT,
+ channel_payer_id VARCHAR(128),
+ channel_pay_no VARCHAR(128),
+ PRIMARY KEY (refund_id)
+ );
+ COMMENT ON COLUMN dwd_refund_Ex.refund_id IS '退款流水主键。每条退款记录唯一 ID(雪花ID风格长整型)。 | 来源: id | 角色: 主键';
+ COMMENT ON COLUMN dwd_refund_Ex.tenant_name IS '租户名称,例如“朗朗桌球”。与租户维度中的名称冗余。 | 来源: tenantName';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_sn IS '支付流水内部序号。退款记录中样本全部为 0,未看到实际使用场景,含义未说明。 | 来源: pay_sn';
+ COMMENT ON COLUMN dwd_refund_Ex.refund_amount IS '本次退款金额(正数)设计字段,样本为 0.00,实际使用 pay_amount。 | 来源: refund_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.round_amount IS '退款过程中的舍入/抹零金额。 | 来源: round_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.balance_frozen_amount IS '与会员余额相关的冻结金额,样本为 0。 | 来源: balance_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.card_frozen_amount IS '与某张会员卡余额相关的冻结金额,样本为 0。 | 来源: card_frozen_amount';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_status IS '退款状态枚举。样本中全部为 2(成功/已完成)。 | 来源: pay_status';
+ COMMENT ON COLUMN dwd_refund_Ex.action_type IS '资金动作类型枚举。样本全部为 2(退款)。 | 来源: action_type';
+ COMMENT ON COLUMN dwd_refund_Ex.is_revoke IS '是否为撤销型退款:0=正常退款;1=撤销原支付。 | 来源: is_revoke';
+ COMMENT ON COLUMN dwd_refund_Ex.is_delete IS '逻辑删除标志:0=未删除;1=已逻辑删除。 | 来源: is_delete';
+ COMMENT ON COLUMN dwd_refund_Ex.check_status IS '审核状态。样本全部为 1(已审核/通过)。 | 来源: check_status';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_channel IS '线上支付渠道枚举。样本中全部为 0(线下或默认)。 | 来源: online_pay_channel';
+ COMMENT ON COLUMN dwd_refund_Ex.online_pay_type IS '在线退款类型。样本全部为 0(原路退回)。 | 来源: online_pay_type';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_terminal IS '退款终端类型。样本全部为 1(前台收银端)。 | 来源: pay_terminal';
+ COMMENT ON COLUMN dwd_refund_Ex.pay_config_id IS '支付配置 ID,例如某个具体支付通道(微信商户号、银联通道等)的配置主键。样本全部为 0。 | 来源: pay_config_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.cashier_point_id IS '收银点编号,例如前台1、前台2、自助机等。样本全部为 0。 | 来源: cashier_point_id';
+ COMMENT ON COLUMN dwd_refund_Ex.operator_id IS '执行退款操作的操作员 ID。样本全部为 0。 | 来源: operator_id | 角色: 外键';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_payer_id IS '支付渠道侧的付款人标识,如 openid、银行卡号掩码等。样本全部为空字符串。 | 来源: channel_payer_id';
+ COMMENT ON COLUMN dwd_refund_Ex.channel_pay_no IS '第三方支付平台交易号(如微信支付单号、支付宝交易号等)。当前样本全部为空。 | 来源: channel_pay_no';
diff --git a/tmp/single_ingest/goods_stock_movements.json b/tmp/single_ingest/goods_stock_movements.json
new file mode 100644
index 0000000..5588483
--- /dev/null
+++ b/tmp/single_ingest/goods_stock_movements.json
@@ -0,0 +1,4218 @@
+[
+ {
+ "data": {
+ "total": 5915,
+ "queryDeliveryRecordsList": [
+ {
+ "siteGoodsStockId": 2957911857581957,
+ "siteGoodsId": 2793026183532613,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "阿萨姆",
+ "createTime": "2025-11-09 23:23:34",
+ "startNum": 28,
+ "endNum": 27,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957908562546181,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 23:20:13",
+ "startNum": 60,
+ "endNum": 59,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957905405087621,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 23:17:01",
+ "startNum": 279,
+ "endNum": 278,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957886359998341,
+ "siteGoodsId": 2826003636177861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "长寿街臭干子",
+ "createTime": "2025-11-09 22:57:38",
+ "startNum": 98,
+ "endNum": 96,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957886359703429,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 22:57:38",
+ "startNum": 11,
+ "endNum": 10,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2957886359408517,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 22:57:38",
+ "startNum": 212,
+ "endNum": 211,
+ "changeNum": -1,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957885299511173,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 22:56:33",
+ "startNum": 281,
+ "endNum": 279,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957881233444677,
+ "siteGoodsId": 2794695802065029,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鸡翅三个一份",
+ "createTime": "2025-11-09 22:52:25",
+ "startNum": 7,
+ "endNum": 6,
+ "changeNum": -1,
+ "unit": "份",
+ "price": 18.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957869009637061,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 22:39:59",
+ "startNum": 282,
+ "endNum": 281,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957864363347781,
+ "siteGoodsId": 2794695801409669,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "普通扑克",
+ "createTime": "2025-11-09 22:35:16",
+ "startNum": 16,
+ "endNum": 15,
+ "changeNum": -1,
+ "unit": "盒",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957863619809093,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 22:34:30",
+ "startNum": 61,
+ "endNum": 60,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957863385878341,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 22:34:16",
+ "startNum": 34,
+ "endNum": 33,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957863385452357,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 22:34:16",
+ "startNum": 123,
+ "endNum": 122,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957861202365957,
+ "siteGoodsId": 2794695802065029,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鸡翅三个一份",
+ "createTime": "2025-11-09 22:32:03",
+ "startNum": 8,
+ "endNum": 7,
+ "changeNum": -1,
+ "unit": "份",
+ "price": 18.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957859847671621,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 22:30:40",
+ "startNum": 214,
+ "endNum": 212,
+ "changeNum": -2,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957858456276869,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 22:29:15",
+ "startNum": 283,
+ "endNum": 282,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957858455883653,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 22:29:15",
+ "startNum": 96,
+ "endNum": 95,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957857677790725,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 22:28:28",
+ "startNum": 35,
+ "endNum": 34,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957857677364741,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 22:28:28",
+ "startNum": 119,
+ "endNum": 118,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957857132121925,
+ "siteGoodsId": 2793026174865477,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "水溶C",
+ "createTime": "2025-11-09 22:27:54",
+ "startNum": 55,
+ "endNum": 54,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957857131728709,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 22:27:54",
+ "startNum": 284,
+ "endNum": 283,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957821892152837,
+ "siteGoodsId": 2793025860145221,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "双中支中华",
+ "createTime": "2025-11-09 21:52:03",
+ "startNum": 4,
+ "endNum": 2,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 72.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957815972531717,
+ "siteGoodsId": 2793025862438981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "钻石荷花",
+ "createTime": "2025-11-09 21:46:02",
+ "startNum": 15,
+ "endNum": 13,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 45.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957815972138501,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 21:46:02",
+ "startNum": 285,
+ "endNum": 284,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957815643639621,
+ "siteGoodsId": 2793025862438981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "钻石荷花",
+ "createTime": "2025-11-09 21:45:42",
+ "startNum": 13,
+ "endNum": 15,
+ "changeNum": 2,
+ "unit": "包",
+ "price": 45.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957815530426053,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 21:45:35",
+ "startNum": 286,
+ "endNum": 285,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957815529950917,
+ "siteGoodsId": 2793025862438981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "钻石荷花",
+ "createTime": "2025-11-09 21:45:35",
+ "startNum": 15,
+ "endNum": 13,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 45.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957815167815365,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 21:45:13",
+ "startNum": 287,
+ "endNum": 286,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957814738996741,
+ "siteGoodsId": 2793026176503877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "轻上椰子水",
+ "createTime": "2025-11-09 21:44:47",
+ "startNum": 50,
+ "endNum": 48,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957814478786373,
+ "siteGoodsId": 2793026176503877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "轻上椰子水",
+ "createTime": "2025-11-09 21:44:31",
+ "startNum": 51,
+ "endNum": 50,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957795024752517,
+ "siteGoodsId": 2793026184974405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "卡士",
+ "createTime": "2025-11-09 21:24:44",
+ "startNum": 2,
+ "endNum": 0,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 22.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957788100595589,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 21:17:41",
+ "startNum": 288,
+ "endNum": 287,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957788100300677,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 21:17:41",
+ "startNum": 41,
+ "endNum": 35,
+ "changeNum": -6,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957787478183813,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:17:03",
+ "startNum": 343,
+ "endNum": 307,
+ "changeNum": -36,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957786810420933,
+ "siteGoodsId": 2793026184974405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "卡士",
+ "createTime": "2025-11-09 21:16:22",
+ "startNum": 5,
+ "endNum": 2,
+ "changeNum": -3,
+ "unit": "瓶",
+ "price": 22.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957786577244037,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:16:08",
+ "startNum": 307,
+ "endNum": 343,
+ "changeNum": 36,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "系统",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957786541575685,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:16:06",
+ "startNum": 343,
+ "endNum": 307,
+ "changeNum": -36,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957786283101701,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:15:50",
+ "startNum": 332,
+ "endNum": 343,
+ "changeNum": 11,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957786211487237,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:15:46",
+ "startNum": 331,
+ "endNum": 332,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957786053463557,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 21:15:36",
+ "startNum": 120,
+ "endNum": 119,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957785947672069,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:15:29",
+ "startNum": 319,
+ "endNum": 331,
+ "changeNum": 12,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957785873894917,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 21:15:25",
+ "startNum": 287,
+ "endNum": 288,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957785776590341,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 21:15:19",
+ "startNum": 307,
+ "endNum": 319,
+ "changeNum": 12,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957785236787013,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 21:14:46",
+ "startNum": 35,
+ "endNum": 41,
+ "changeNum": 6,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957783492513477,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 21:13:00",
+ "startNum": 97,
+ "endNum": 96,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957780975586821,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 21:10:26",
+ "startNum": 98,
+ "endNum": 97,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957761222331909,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 20:50:20",
+ "startNum": 121,
+ "endNum": 120,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957750510145413,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 20:39:27",
+ "startNum": 289,
+ "endNum": 287,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957750509686661,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 20:39:27",
+ "startNum": 99,
+ "endNum": 98,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957749929889285,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 20:38:51",
+ "startNum": 291,
+ "endNum": 289,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957749609319941,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 20:38:32",
+ "startNum": 36,
+ "endNum": 35,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957749608992261,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 20:38:32",
+ "startNum": 12,
+ "endNum": 11,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2957730790199173,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 20:19:23",
+ "startNum": 215,
+ "endNum": 214,
+ "changeNum": -1,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957730789789573,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 20:19:23",
+ "startNum": 122,
+ "endNum": 121,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957724530724549,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 20:13:01",
+ "startNum": 319,
+ "endNum": 307,
+ "changeNum": -12,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957723760037701,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 20:12:14",
+ "startNum": 124,
+ "endNum": 123,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957714749919109,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 20:03:04",
+ "startNum": 124,
+ "endNum": 122,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957700557246149,
+ "siteGoodsId": 2793026184646725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "冰红茶",
+ "createTime": "2025-11-09 19:48:38",
+ "startNum": 49,
+ "endNum": 48,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957700556820165,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 19:48:38",
+ "startNum": 125,
+ "endNum": 124,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957699263696389,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 19:47:19",
+ "startNum": 292,
+ "endNum": 291,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957684739952325,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 19:32:32",
+ "startNum": 100,
+ "endNum": 99,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957678126419781,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 19:25:49",
+ "startNum": 331,
+ "endNum": 319,
+ "changeNum": -12,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957651515838277,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 18:58:44",
+ "startNum": 343,
+ "endNum": 331,
+ "changeNum": -12,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957651515428677,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 18:58:44",
+ "startNum": 42,
+ "endNum": 36,
+ "changeNum": -6,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957650904927749,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 18:58:07",
+ "startNum": 101,
+ "endNum": 100,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957648287797125,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 18:55:27",
+ "startNum": 217,
+ "endNum": 215,
+ "changeNum": -2,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957635479687045,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 18:42:26",
+ "startNum": 43,
+ "endNum": 42,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957635479392133,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 18:42:26",
+ "startNum": 126,
+ "endNum": 125,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957635296677381,
+ "siteGoodsId": 2794695801753733,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "掼蛋扑克",
+ "createTime": "2025-11-09 18:42:14",
+ "startNum": 54,
+ "endNum": 52,
+ "changeNum": -2,
+ "unit": "盒",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957633426329285,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 18:40:20",
+ "startNum": 294,
+ "endNum": 292,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957633425870533,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 18:40:20",
+ "startNum": 45,
+ "endNum": 43,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957622553579013,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 18:29:17",
+ "startNum": 296,
+ "endNum": 294,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957610094841669,
+ "siteGoodsId": 2793025860145221,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "双中支中华",
+ "createTime": "2025-11-09 18:16:36",
+ "startNum": 5,
+ "endNum": 4,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 72.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957609373077381,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 18:15:52",
+ "startNum": 62,
+ "endNum": 61,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957609372782469,
+ "siteGoodsId": 2793026177486917,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈AD钙奶",
+ "createTime": "2025-11-09 18:15:52",
+ "startNum": 78,
+ "endNum": 77,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957606919360325,
+ "siteGoodsId": 2826003636177861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "长寿街臭干子",
+ "createTime": "2025-11-09 18:13:22",
+ "startNum": 100,
+ "endNum": 98,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957606918901573,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 18:13:22",
+ "startNum": 302,
+ "endNum": 296,
+ "changeNum": -6,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957605951278789,
+ "siteGoodsId": 2793025862799429,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "软玉溪",
+ "createTime": "2025-11-09 18:12:23",
+ "startNum": 21,
+ "endNum": 20,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 28.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957603839545221,
+ "siteGoodsId": 2793026184646725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "冰红茶",
+ "createTime": "2025-11-09 18:10:14",
+ "startNum": 50,
+ "endNum": 49,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957601966706565,
+ "siteGoodsId": 2794695801753733,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "掼蛋扑克",
+ "createTime": "2025-11-09 18:08:20",
+ "startNum": 52,
+ "endNum": 54,
+ "changeNum": 2,
+ "unit": "盒",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957601853853573,
+ "siteGoodsId": 2794695801753733,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "掼蛋扑克",
+ "createTime": "2025-11-09 18:08:13",
+ "startNum": 54,
+ "endNum": 52,
+ "changeNum": -2,
+ "unit": "盒",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957599397908357,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 18:05:43",
+ "startNum": 102,
+ "endNum": 101,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957599270195077,
+ "siteGoodsId": 2793026175356997,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "脉动",
+ "createTime": "2025-11-09 18:05:36",
+ "startNum": 26,
+ "endNum": 25,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957587268013765,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 17:53:23",
+ "startNum": 46,
+ "endNum": 45,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957585881730949,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 17:51:58",
+ "startNum": 127,
+ "endNum": 126,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957585881321349,
+ "siteGoodsId": 2793026185515077,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "雪碧",
+ "createTime": "2025-11-09 17:51:58",
+ "startNum": 62,
+ "endNum": 61,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957578616377029,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 17:44:35",
+ "startNum": 128,
+ "endNum": 127,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957573882465989,
+ "siteGoodsId": 2793025861505093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红利群",
+ "createTime": "2025-11-09 17:39:46",
+ "startNum": 10,
+ "endNum": 9,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 26.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957564018478597,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 17:29:44",
+ "startNum": 125,
+ "endNum": 124,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957550403538437,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 17:15:53",
+ "startNum": 345,
+ "endNum": 343,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957543734349701,
+ "siteGoodsId": 2794695801409669,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "普通扑克",
+ "createTime": "2025-11-09 17:09:06",
+ "startNum": 17,
+ "endNum": 16,
+ "changeNum": -1,
+ "unit": "盒",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957538712670021,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 17:03:59",
+ "startNum": 126,
+ "endNum": 125,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957535156031173,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 17:00:22",
+ "startNum": 131,
+ "endNum": 128,
+ "changeNum": -3,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957531838844613,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 16:57:00",
+ "startNum": 132,
+ "endNum": 131,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957531838467781,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 16:57:00",
+ "startNum": 303,
+ "endNum": 302,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957529797349189,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 16:54:55",
+ "startNum": 304,
+ "endNum": 303,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957529796890437,
+ "siteGoodsId": 2793026174865477,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "水溶C",
+ "createTime": "2025-11-09 16:54:55",
+ "startNum": 57,
+ "endNum": 55,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957529061461893,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 16:54:10",
+ "startNum": 301,
+ "endNum": 304,
+ "changeNum": 3,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957528487595717,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 16:53:35",
+ "startNum": 304,
+ "endNum": 301,
+ "changeNum": -3,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957528359833477,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 16:53:28",
+ "startNum": 344,
+ "endNum": 345,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ }
+ ]
+ },
+ "code": 0
+ },
+ {
+ "data": {
+ "total": 5915,
+ "queryDeliveryRecordsList": [
+ {
+ "siteGoodsStockId": 2957513359134405,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 16:38:12",
+ "startNum": 128,
+ "endNum": 126,
+ "changeNum": -2,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957511204048773,
+ "siteGoodsId": 2793026185154629,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "百威235毫升",
+ "createTime": "2025-11-09 16:36:00",
+ "startNum": 345,
+ "endNum": 344,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350541
+ },
+ {
+ "siteGoodsStockId": 2957493084458885,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 16:17:35",
+ "startNum": 129,
+ "endNum": 128,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957487737163269,
+ "siteGoodsId": 2794695801753733,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "掼蛋扑克",
+ "createTime": "2025-11-09 16:12:08",
+ "startNum": 56,
+ "endNum": 54,
+ "changeNum": -2,
+ "unit": "盒",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957465626463749,
+ "siteGoodsId": 2794695800934533,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "一次性手套",
+ "createTime": "2025-11-09 15:49:39",
+ "startNum": 130,
+ "endNum": 129,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2957465564696069,
+ "siteGoodsId": 2793026176503877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "轻上椰子水",
+ "createTime": "2025-11-09 15:49:35",
+ "startNum": 52,
+ "endNum": 51,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957465565089285,
+ "siteGoodsId": 2793026176995397,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "维他柠檬茶",
+ "createTime": "2025-11-09 15:49:35",
+ "startNum": 37,
+ "endNum": 36,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957419716153157,
+ "siteGoodsId": 2793026180501573,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东鹏特饮",
+ "createTime": "2025-11-09 15:02:56",
+ "startNum": 101,
+ "endNum": 99,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 7.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957416232717637,
+ "siteGoodsId": 2826003636177861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "长寿街臭干子",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 100,
+ "changeNum": 100,
+ "unit": "包",
+ "price": 2.0,
+ "operatorName": "系统",
+ "changeNumA": -100,
+ "startNumA": 100,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416230948165,
+ "siteGoodsId": 2793025845399621,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "奥利奥饼干",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "盒",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 10,
+ "startNumA": 0,
+ "endNumA": 10,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231013701,
+ "siteGoodsId": 2793025845399621,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "奥利奥饼干",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 10,
+ "changeNum": 10,
+ "unit": "盒",
+ "price": 12.0,
+ "operatorName": "系统",
+ "changeNumA": -10,
+ "startNumA": 10,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231341381,
+ "siteGoodsId": 2793025848610885,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "麻辣王子",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 1,
+ "endNum": 11,
+ "changeNum": 10,
+ "unit": "包",
+ "price": 12.0,
+ "operatorName": "系统",
+ "changeNumA": -10,
+ "startNumA": 10,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416232324421,
+ "siteGoodsId": 2793025847595077,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "鱿鱼丝",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "包",
+ "price": 30.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 15,
+ "startNumA": 0,
+ "endNumA": 15,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416232668485,
+ "siteGoodsId": 2826003636177861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "长寿街臭干子",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "包",
+ "price": 2.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 100,
+ "startNumA": 0,
+ "endNumA": 100,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416233061701,
+ "siteGoodsId": 2793026434863237,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "酒鬼花生",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 15,
+ "changeNum": 15,
+ "unit": "包",
+ "price": 8.0,
+ "operatorName": "系统",
+ "changeNumA": -15,
+ "startNumA": 15,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231292229,
+ "siteGoodsId": 2793025848610885,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "麻辣王子",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 1,
+ "endNum": 1,
+ "changeNum": 0,
+ "unit": "包",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 10,
+ "startNumA": 0,
+ "endNumA": 10,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416233012549,
+ "siteGoodsId": 2793026434863237,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "酒鬼花生",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "包",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 15,
+ "startNumA": 0,
+ "endNumA": 15,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231701829,
+ "siteGoodsId": 2793026187235397,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "奥利奥迷你可可",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 14,
+ "changeNum": 14,
+ "unit": "份",
+ "price": 8.0,
+ "operatorName": "系统",
+ "changeNumA": -14,
+ "startNumA": 14,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416232029509,
+ "siteGoodsId": 2793025848102981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "透明袋无穷鸡翅",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 10,
+ "changeNum": 10,
+ "unit": "包",
+ "price": 20.0,
+ "operatorName": "系统",
+ "changeNumA": -10,
+ "startNumA": 10,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231652677,
+ "siteGoodsId": 2793026187235397,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "奥利奥迷你可可",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "份",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 14,
+ "startNumA": 0,
+ "endNumA": 14,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416231980357,
+ "siteGoodsId": 2793025848102981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "透明袋无穷鸡翅",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 0,
+ "changeNum": 0,
+ "unit": "包",
+ "price": 20.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 10,
+ "startNumA": 0,
+ "endNumA": 10,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957416232373573,
+ "siteGoodsId": 2793025847595077,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "鱿鱼丝",
+ "createTime": "2025-11-09 14:59:24",
+ "startNum": 0,
+ "endNum": 15,
+ "changeNum": 15,
+ "unit": "包",
+ "price": 30.0,
+ "operatorName": "系统",
+ "changeNumA": -15,
+ "startNumA": 15,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957399093202437,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 14:41:58",
+ "startNum": 305,
+ "endNum": 304,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957365000277509,
+ "siteGoodsId": 2834064312256837,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "南北特卤豆干80g",
+ "createTime": "2025-11-09 14:07:17",
+ "startNum": 6,
+ "endNum": 5,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957223509691717,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 11:43:21",
+ "startNum": 17,
+ "endNum": 17,
+ "changeNum": 0,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 200,
+ "startNumA": 0,
+ "endNumA": 200,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957223509790021,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 11:43:21",
+ "startNum": 17,
+ "endNum": 217,
+ "changeNum": 200,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "系统",
+ "changeNumA": -200,
+ "startNumA": 200,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957223510052165,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 2,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 11:43:21",
+ "startNum": 14,
+ "endNum": 14,
+ "changeNum": 0,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珍",
+ "changeNumA": 60,
+ "startNumA": 0,
+ "endNumA": 60,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957223510117701,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 8,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 11:43:21",
+ "startNum": 14,
+ "endNum": 74,
+ "changeNum": 60,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "系统",
+ "changeNumA": -60,
+ "startNumA": 60,
+ "endNumA": 0,
+ "remark": "系统自动领用",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2957011016961861,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 08:07:11",
+ "startNum": 133,
+ "endNum": 132,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957011017355077,
+ "siteGoodsId": 2793025861505093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红利群",
+ "createTime": "2025-11-09 08:07:11",
+ "startNum": 11,
+ "endNum": 10,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 26.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2957001761820485,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 07:57:47",
+ "startNum": 132,
+ "endNum": 133,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957001653571397,
+ "siteGoodsId": 2793026184302661,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "红牛",
+ "createTime": "2025-11-09 07:57:40",
+ "startNum": 213,
+ "endNum": 214,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957001570438981,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 07:57:35",
+ "startNum": 100,
+ "endNum": 102,
+ "changeNum": 2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957001428422469,
+ "siteGoodsId": 2793026184302661,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "红牛",
+ "createTime": "2025-11-09 07:57:26",
+ "startNum": 212,
+ "endNum": 213,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957001365524293,
+ "siteGoodsId": 2793026184302661,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "红牛",
+ "createTime": "2025-11-09 07:57:22",
+ "startNum": 211,
+ "endNum": 212,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957001257897477,
+ "siteGoodsId": 2793026433749125,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "香辣鱼皮",
+ "createTime": "2025-11-09 07:57:16",
+ "startNum": 6,
+ "endNum": 7,
+ "changeNum": 1,
+ "unit": "包",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957001192721925,
+ "siteGoodsId": 2793026432585861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "脆升升",
+ "createTime": "2025-11-09 07:57:12",
+ "startNum": 1,
+ "endNum": 2,
+ "changeNum": 1,
+ "unit": "包",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2957000886095365,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 07:56:53",
+ "startNum": 131,
+ "endNum": 132,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "系统",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2957000210648773,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 07:56:12",
+ "startNum": 132,
+ "endNum": 131,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956996538306245,
+ "siteGoodsId": 2906983124748485,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "1000服务费",
+ "createTime": "2025-11-09 07:52:28",
+ "startNum": 8,
+ "endNum": 10,
+ "changeNum": 2,
+ "unit": "个",
+ "price": 1000.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2956996336226117,
+ "siteGoodsId": 2906983124748485,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "1000服务费",
+ "createTime": "2025-11-09 07:52:15",
+ "startNum": 5,
+ "endNum": 8,
+ "changeNum": 3,
+ "unit": "个",
+ "price": 1000.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2956993780731589,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 07:49:39",
+ "startNum": 306,
+ "endNum": 305,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956993780436677,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 07:49:39",
+ "startNum": 64,
+ "endNum": 62,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956993662586757,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 07:49:32",
+ "startNum": 305,
+ "endNum": 306,
+ "changeNum": 1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "系统",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956993662406533,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 07:49:32",
+ "startNum": 62,
+ "endNum": 64,
+ "changeNum": 2,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "系统",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956993627098949,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 07:49:30",
+ "startNum": 306,
+ "endNum": 305,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956993626804037,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 07:49:30",
+ "startNum": 64,
+ "endNum": 62,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956991904566789,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 07:47:45",
+ "startNum": 133,
+ "endNum": 132,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956991000448901,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 07:46:50",
+ "startNum": 307,
+ "endNum": 306,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956990831595333,
+ "siteGoodsId": 2793026178977861,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "白桦树汁",
+ "createTime": "2025-11-09 07:46:39",
+ "startNum": 40,
+ "endNum": 38,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956990830825285,
+ "siteGoodsId": 2793025855950917,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "明治小杯冰淇淋",
+ "createTime": "2025-11-09 07:46:39",
+ "startNum": 2,
+ "endNum": 1,
+ "changeNum": -1,
+ "unit": "杯",
+ "price": 15.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791942087561093,
+ "goodsSecondCategoryId": 2792035069284229
+ },
+ {
+ "siteGoodsStockId": 2956990831218501,
+ "siteGoodsId": 2793025863503941,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "粗和天下",
+ "createTime": "2025-11-09 07:46:39",
+ "startNum": 5,
+ "endNum": 3,
+ "changeNum": -2,
+ "unit": "包",
+ "price": 125.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956990832004933,
+ "siteGoodsId": 2793026433077381,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "喜之郎果冻",
+ "createTime": "2025-11-09 07:46:39",
+ "startNum": 17,
+ "endNum": 14,
+ "changeNum": -3,
+ "unit": "包",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2791948300259205
+ },
+ {
+ "siteGoodsStockId": 2956979156586181,
+ "siteGoodsId": 2906983124748485,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "1000服务费",
+ "createTime": "2025-11-09 07:34:47",
+ "startNum": 7,
+ "endNum": 5,
+ "changeNum": -2,
+ "unit": "个",
+ "price": 1000.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2956968345538245,
+ "siteGoodsId": 2793025851560005,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "合味道泡面",
+ "createTime": "2025-11-09 07:23:47",
+ "startNum": 20,
+ "endNum": 18,
+ "changeNum": -2,
+ "unit": "桶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956968346291909,
+ "siteGoodsId": 2793026184482885,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "旺仔牛奶",
+ "createTime": "2025-11-09 07:23:47",
+ "startNum": 84,
+ "endNum": 83,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956968345915077,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 07:23:47",
+ "startNum": 308,
+ "endNum": 307,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956947893604229,
+ "siteGoodsId": 2793025855000645,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "明治炼乳红豆",
+ "createTime": "2025-11-09 07:02:59",
+ "startNum": 12,
+ "endNum": 11,
+ "changeNum": -1,
+ "unit": "个",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791942087561093,
+ "goodsSecondCategoryId": 2792035069284229
+ },
+ {
+ "siteGoodsStockId": 2956947893227397,
+ "siteGoodsId": 2793025851560005,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "合味道泡面",
+ "createTime": "2025-11-09 07:02:59",
+ "startNum": 21,
+ "endNum": 20,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956928116526981,
+ "siteGoodsId": 2793026176503877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "轻上椰子水",
+ "createTime": "2025-11-09 06:42:52",
+ "startNum": 53,
+ "endNum": 52,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956928116920197,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 06:42:52",
+ "startNum": 309,
+ "endNum": 308,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956925698150085,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 06:40:24",
+ "startNum": 13,
+ "endNum": 12,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956925698543301,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 06:40:24",
+ "startNum": 19,
+ "endNum": 17,
+ "changeNum": -2,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956915514822469,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 06:30:02",
+ "startNum": 134,
+ "endNum": 133,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956906569944901,
+ "siteGoodsId": 2793025862438981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "钻石荷花",
+ "createTime": "2025-11-09 06:20:57",
+ "startNum": 16,
+ "endNum": 15,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 45.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956906015641093,
+ "siteGoodsId": 2793025859375173,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "50 和成天下",
+ "createTime": "2025-11-09 06:20:23",
+ "startNum": 7,
+ "endNum": 6,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 65.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350533,
+ "goodsSecondCategoryId": 2790683528350534
+ },
+ {
+ "siteGoodsStockId": 2956903260835333,
+ "siteGoodsId": 2868240313094021,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "蜂蜜水",
+ "createTime": "2025-11-09 06:17:35",
+ "startNum": 65,
+ "endNum": 64,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956897887063749,
+ "siteGoodsId": 2793026176503877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "轻上椰子水",
+ "createTime": "2025-11-09 06:12:07",
+ "startNum": 54,
+ "endNum": 53,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956897886654149,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 06:12:07",
+ "startNum": 310,
+ "endNum": 309,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956890625167173,
+ "siteGoodsId": 2793025844727877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红烧牛肉面",
+ "createTime": "2025-11-09 06:04:43",
+ "startNum": 41,
+ "endNum": 40,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956883444469573,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 05:57:25",
+ "startNum": 312,
+ "endNum": 310,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956848034664133,
+ "siteGoodsId": 2793025860145221,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "双中支中华",
+ "createTime": "2025-11-09 05:21:24",
+ "startNum": 6,
+ "endNum": 5,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 72.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956836527771525,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 05:09:41",
+ "startNum": 14,
+ "endNum": 13,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956819500355397,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 04:52:22",
+ "startNum": 314,
+ "endNum": 312,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956811144335173,
+ "siteGoodsId": 2793025862438981,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "钻石荷花",
+ "createTime": "2025-11-09 04:43:52",
+ "startNum": 17,
+ "endNum": 16,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 45.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956806838750917,
+ "siteGoodsId": 2793025863290949,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "跨越贵烟",
+ "createTime": "2025-11-09 04:39:29",
+ "startNum": 5,
+ "endNum": 4,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 28.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956806838374085,
+ "siteGoodsId": 2793025860145221,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "双中支中华",
+ "createTime": "2025-11-09 04:39:29",
+ "startNum": 7,
+ "endNum": 6,
+ "changeNum": -1,
+ "unit": "包",
+ "price": 72.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2792062778003333,
+ "goodsSecondCategoryId": 2792063209623429
+ },
+ {
+ "siteGoodsStockId": 2956797945794373,
+ "siteGoodsId": 2802099478416453,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "清洁费150",
+ "createTime": "2025-11-09 04:30:27",
+ "startNum": 4,
+ "endNum": 5,
+ "changeNum": 1,
+ "unit": "份",
+ "price": 150.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793217944864581,
+ "goodsSecondCategoryId": 2793218343257925
+ },
+ {
+ "siteGoodsStockId": 2956795142950405,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 04:27:36",
+ "startNum": 47,
+ "endNum": 46,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956794370756485,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 04:26:48",
+ "startNum": 16,
+ "endNum": 14,
+ "changeNum": -2,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956792338583365,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 04:24:44",
+ "startNum": 102,
+ "endNum": 100,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956792338190149,
+ "siteGoodsId": 2793026176012357,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "哇哈哈矿泉水",
+ "createTime": "2025-11-09 04:24:44",
+ "startNum": 316,
+ "endNum": 314,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956792338960197,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 04:24:44",
+ "startNum": 136,
+ "endNum": 134,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956792339353413,
+ "siteGoodsId": 2793026184302661,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红牛",
+ "createTime": "2025-11-09 04:24:44",
+ "startNum": 213,
+ "endNum": 211,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956792337780549,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 04:24:44",
+ "startNum": 49,
+ "endNum": 47,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956787829510021,
+ "siteGoodsId": 2791953867886725,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "东方树叶",
+ "createTime": "2025-11-09 04:20:09",
+ "startNum": 138,
+ "endNum": 136,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 8.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956787829903237,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 04:20:09",
+ "startNum": 104,
+ "endNum": 102,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956782769426117,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 04:15:00",
+ "startNum": 15,
+ "endNum": 14,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956782769049285,
+ "siteGoodsId": 2793025844727877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红烧牛肉面",
+ "createTime": "2025-11-09 04:15:00",
+ "startNum": 43,
+ "endNum": 41,
+ "changeNum": -2,
+ "unit": "桶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956779655155589,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 04:11:50",
+ "startNum": 50,
+ "endNum": 49,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956775329386309,
+ "siteGoodsId": 2793026180993093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "农夫山泉苏打水",
+ "createTime": "2025-11-09 04:07:26",
+ "startNum": 51,
+ "endNum": 50,
+ "changeNum": -1,
+ "unit": "瓶",
+ "price": 6.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956770987544261,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 04:03:01",
+ "startNum": 18,
+ "endNum": 16,
+ "changeNum": -2,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956769111445381,
+ "siteGoodsId": 2793025849102405,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "火鸡面",
+ "createTime": "2025-11-09 04:01:07",
+ "startNum": 17,
+ "endNum": 15,
+ "changeNum": -2,
+ "unit": "桶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956769111838597,
+ "siteGoodsId": 2793025844727877,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红烧牛肉面",
+ "createTime": "2025-11-09 04:01:07",
+ "startNum": 44,
+ "endNum": 43,
+ "changeNum": -1,
+ "unit": "桶",
+ "price": 12.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2791941988405125,
+ "goodsSecondCategoryId": 2793236829620037
+ },
+ {
+ "siteGoodsStockId": 2956762351472325,
+ "siteGoodsId": 2793026183041093,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "可乐",
+ "createTime": "2025-11-09 03:54:14",
+ "startNum": 106,
+ "endNum": 104,
+ "changeNum": -2,
+ "unit": "瓶",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956762351865541,
+ "siteGoodsId": 2793026184302661,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "红牛",
+ "createTime": "2025-11-09 03:54:14",
+ "startNum": 216,
+ "endNum": 213,
+ "changeNum": -3,
+ "unit": "瓶",
+ "price": 10.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2790683528350539,
+ "goodsSecondCategoryId": 2790683528350540
+ },
+ {
+ "siteGoodsStockId": 2956752564407813,
+ "siteGoodsId": 2794695802065029,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鸡翅三个一份",
+ "createTime": "2025-11-09 03:44:17",
+ "startNum": 10,
+ "endNum": 8,
+ "changeNum": -2,
+ "unit": "份",
+ "price": 18.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956745942142789,
+ "siteGoodsId": 2793025849593925,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "地道肠",
+ "createTime": "2025-11-09 03:37:33",
+ "startNum": 22,
+ "endNum": 19,
+ "changeNum": -3,
+ "unit": "根",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956741521739589,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 1,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 03:33:03",
+ "startNum": 22,
+ "endNum": 18,
+ "changeNum": -4,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ },
+ {
+ "siteGoodsStockId": 2956741348969989,
+ "siteGoodsId": 2793025845825605,
+ "siteId": 2790685415443269,
+ "tenantId": 2790683160709957,
+ "stockType": 4,
+ "goodsName": "鱼蛋",
+ "createTime": "2025-11-09 03:32:52",
+ "startNum": 20,
+ "endNum": 22,
+ "changeNum": 2,
+ "unit": "份",
+ "price": 5.0,
+ "operatorName": "收银员:郑丽珊",
+ "changeNumA": 0,
+ "startNumA": 0,
+ "endNumA": 0,
+ "remark": "",
+ "goodsCategoryId": 2793220945250117,
+ "goodsSecondCategoryId": 2793221283104581
+ }
+ ]
+ },
+ "code": 0
+ }
+]
\ No newline at end of file
diff --git a/tmp/temp_chinese.txt b/tmp/temp_chinese.txt
new file mode 100644
index 0000000..e3a3e0d
--- /dev/null
+++ b/tmp/temp_chinese.txt
@@ -0,0 +1 @@
+含义
diff --git a/tmp/tmp_debug_sql.py b/tmp/tmp_debug_sql.py
new file mode 100644
index 0000000..12dc104
--- /dev/null
+++ b/tmp/tmp_debug_sql.py
@@ -0,0 +1,29 @@
+import os, psycopg2
+from etl_billiards.tasks.dwd_load_task import DwdLoadTask
+
+dwd_table="billiards_dwd.dwd_table_fee_log"
+ods_table="billiards_ods.table_fee_transactions"
+conn=psycopg2.connect(os.environ["PG_DSN"])
+cur=conn.cursor()
+task=DwdLoadTask(config={}, db_connection=None, api_client=None, logger=None)
+cur.execute("SELECT column_name FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_dwd", "dwd_table_fee_log"))
+dwd_cols=[r[0].lower() for r in cur.fetchall()]
+cur.execute("SELECT column_name FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_ods", "table_fee_transactions"))
+ods_cols=[r[0].lower() for r in cur.fetchall()]
+cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_dwd", "dwd_table_fee_log"))
+dwd_types={r[0].lower(): r[1].lower() for r in cur.fetchall()}
+cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_ods", "table_fee_transactions"))
+ods_types={r[0].lower(): r[1].lower() for r in cur.fetchall()}
+mapping=task.FACT_MAPPINGS.get(dwd_table)
+if mapping:
+ insert_cols=[d for d,o,_ in mapping if o in ods_cols]
+ select_exprs=[task._cast_expr(o,cast_type) for d,o,cast_type in mapping if o in ods_cols]
+else:
+ insert_cols=[c for c in dwd_cols if c in ods_cols and c not in task.SCD_COLS]
+ select_exprs=task._build_fact_select_exprs(insert_cols,dwd_types,ods_types)
+print('insert_cols', insert_cols)
+print('select_exprs', select_exprs)
+sql=f"INSERT INTO {task._format_table(dwd_table,'billiards_dwd')} ({', '.join(f'\"{c}\"' for c in insert_cols)}) SELECT {', '.join(select_exprs)} FROM {task._format_table(ods_table,'billiards_ods')}"
+print(sql)
+cur.close(); conn.close()
+
diff --git a/tmp/tmp_drop_dwd.py b/tmp/tmp_drop_dwd.py
new file mode 100644
index 0000000..1ea2e57
--- /dev/null
+++ b/tmp/tmp_drop_dwd.py
@@ -0,0 +1,7 @@
+import os, psycopg2
+conn=psycopg2.connect(os.environ["PG_DSN"])
+conn.autocommit=True
+cur=conn.cursor()
+cur.execute('DROP SCHEMA IF EXISTS billiards_dwd CASCADE')
+cur.close(); conn.close()
+print('dropped billiards_dwd')
diff --git a/tmp/tmp_dwd_tasks.py b/tmp/tmp_dwd_tasks.py
new file mode 100644
index 0000000..5c07a51
--- /dev/null
+++ b/tmp/tmp_dwd_tasks.py
@@ -0,0 +1,19 @@
+import os
+import psycopg2
+
+DSN = os.environ.get('PG_DSN')
+store_id = int(os.environ.get('STORE_ID','2790685415443269'))
+conn = psycopg2.connect(DSN)
+conn.autocommit = True
+cur = conn.cursor()
+rows = []
+for code in ('INIT_DWD_SCHEMA','DWD_LOAD_FROM_ODS','DWD_QUALITY_CHECK'):
+ cur.execute("SELECT task_id FROM etl_admin.etl_task WHERE task_code=%s AND store_id=%s", (code, store_id))
+ if cur.fetchone():
+ cur.execute("UPDATE etl_admin.etl_task SET enabled=TRUE, updated_at=now() WHERE task_code=%s AND store_id=%s", (code, store_id))
+ rows.append((code, 'updated'))
+ else:
+ cur.execute("INSERT INTO etl_admin.etl_task(task_code,store_id,enabled,cursor_field,window_minutes_default,overlap_seconds,page_size,params) VALUES (%s,%s,TRUE,NULL,60,120,1000,'{}') RETURNING task_id", (code, store_id))
+ rows.append((code, 'inserted', cur.fetchone()[0]))
+print(rows)
+cur.close(); conn.close()
diff --git a/tmp/tmp_problems.py b/tmp/tmp_problems.py
new file mode 100644
index 0000000..2eb5869
--- /dev/null
+++ b/tmp/tmp_problems.py
@@ -0,0 +1,28 @@
+import os, psycopg2
+from etl_billiards.tasks.dwd_load_task import DwdLoadTask
+
+conn=psycopg2.connect(os.environ['PG_DSN'])
+cur=conn.cursor()
+problems=[]
+for dwd_table, ods_table in DwdLoadTask.TABLE_MAP.items():
+ if dwd_table.split('.')[-1].startswith('dwd_'):
+ if '.' in dwd_table:
+ dschema, dtable = dwd_table.split('.')
+ else:
+ dschema, dtable = 'billiards_dwd', dwd_table
+ if '.' in ods_table:
+ oschema, otable = ods_table.split('.')
+ else:
+ oschema, otable = 'billiards_ods', ods_table
+ cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", (dschema,dtable))
+ dcols={r[0].lower():r[1].lower() for r in cur.fetchall()}
+ cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", (oschema,otable))
+ ocols={r[0].lower():r[1].lower() for r in cur.fetchall()}
+ common=set(dcols)&set(ocols)
+ missing_dwd=list(set(ocols)-set(dcols))
+ missing_ods=list(set(dcols)-set(ocols))
+ mismatches=[(c,dcols[c],ocols[c]) for c in sorted(common) if dcols[c]!=ocols[c]]
+ problems.append((dwd_table,missing_dwd,missing_ods,mismatches))
+cur.close();conn.close()
+for p in problems:
+ print(p)
diff --git a/tmp/tmp_run_sql.py b/tmp/tmp_run_sql.py
new file mode 100644
index 0000000..8df87d3
--- /dev/null
+++ b/tmp/tmp_run_sql.py
@@ -0,0 +1,26 @@
+import os, psycopg2
+from etl_billiards.tasks.dwd_load_task import DwdLoadTask
+
+dwd_table="billiards_dwd.dwd_table_fee_log"
+ods_table="billiards_ods.table_fee_transactions"
+conn=psycopg2.connect(os.environ["PG_DSN"])
+cur=conn.cursor()
+task=DwdLoadTask(config={}, db_connection=None, api_client=None, logger=None)
+cur.execute("SELECT column_name FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_dwd", "dwd_table_fee_log"))
+dwd_cols=[r[0].lower() for r in cur.fetchall()]
+cur.execute("SELECT column_name FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_ods", "table_fee_transactions"))
+ods_cols=[r[0].lower() for r in cur.fetchall()]
+cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_dwd", "dwd_table_fee_log"))
+dwd_types={r[0].lower(): r[1].lower() for r in cur.fetchall()}
+cur.execute("SELECT column_name,data_type FROM information_schema.columns WHERE table_schema=%s AND table_name=%s", ("billiards_ods", "table_fee_transactions"))
+ods_types={r[0].lower(): r[1].lower() for r in cur.fetchall()}
+mapping=task.FACT_MAPPINGS.get(dwd_table)
+insert_cols=[d for d,o,_ in mapping if o in ods_cols]
+select_exprs=[task._cast_expr(o,cast_type) for d,o,cast_type in mapping if o in ods_cols]
+sql=f"INSERT INTO {task._format_table(dwd_table,'billiards_dwd')} ({', '.join(f'\"{c}\"' for c in insert_cols)}) SELECT {', '.join(select_exprs)} FROM {task._format_table(ods_table,'billiards_ods')} LIMIT 1"
+print(sql)
+cur.execute(sql)
+conn.commit()
+print('ok')
+cur.close(); conn.close()
+
diff --git a/非球接口API.md b/tmp/非球接口API.md
similarity index 100%
rename from 非球接口API.md
rename to tmp/非球接口API.md
diff --git a/开发笔记/记录.md b/开发笔记/记录.md
new file mode 100644
index 0000000..5998a4c
--- /dev/null
+++ b/开发笔记/记录.md
@@ -0,0 +1,4 @@
+
+
+
+API遵循 RESTful API 规范
\ No newline at end of file